init
This commit is contained in:
		
						commit
						03e58778dd
					
				
							
								
								
									
										21
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								go.mod
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
module icbcwifi
 | 
			
		||||
 | 
			
		||||
go 1.19
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	b612.me/starlog v1.3.0
 | 
			
		||||
	b612.me/starnet v0.1.5
 | 
			
		||||
	b612.me/staros v1.1.4
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	b612.me/notify v1.2.0 // indirect
 | 
			
		||||
	b612.me/starcrypto v0.0.1 // indirect
 | 
			
		||||
	b612.me/stario v0.0.7 // indirect
 | 
			
		||||
	b612.me/starmap v1.2.0 // indirect
 | 
			
		||||
	b612.me/win32api v0.0.1 // indirect
 | 
			
		||||
	b612.me/wincmd v0.0.1 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect
 | 
			
		||||
	golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 // indirect
 | 
			
		||||
	golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										36
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								go.sum
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
b612.me/notify v1.2.0 h1:RedXNMLqY+TozalmdIUM27EFvZp06pzeqHn/F9G1eEs=
 | 
			
		||||
b612.me/notify v1.2.0/go.mod h1:EPctpKCVnoZO1hUJTRYpOw3huTemua+SGNIuUCsnzOc=
 | 
			
		||||
b612.me/starcrypto v0.0.1 h1:xGngzXPUrVbqtWzNw2e+0eWsdG7GG1/X+ONDGIzdriI=
 | 
			
		||||
b612.me/starcrypto v0.0.1/go.mod h1:hz0xRnfWNpYOlVrIPoGrQOWPibq4YiUZ7qN5tsQbzPo=
 | 
			
		||||
b612.me/stario v0.0.5/go.mod h1:or4ssWcxQSjMeu+hRKEgtp0X517b3zdlEOAms8Qscvw=
 | 
			
		||||
b612.me/stario v0.0.7 h1:QbQcsHCVLE6vRgVrPN4+9DGiSaC6IWdtm4ClL2tpMUg=
 | 
			
		||||
b612.me/stario v0.0.7/go.mod h1:or4ssWcxQSjMeu+hRKEgtp0X517b3zdlEOAms8Qscvw=
 | 
			
		||||
b612.me/starlog v1.3.0 h1:GV/qhZ1MssUWedT5YHDltGbq+ZUoB58ysNY/yI7QuDw=
 | 
			
		||||
b612.me/starlog v1.3.0/go.mod h1:qydvFLzkSg+2TrgNvc+bbx5qC6GaH+dtJUjgQjRL0ro=
 | 
			
		||||
b612.me/starmap v1.2.0 h1:sRUeMRUqOyb3pAQln5U6V07kIYp0714Z3gJ/g2nCJXc=
 | 
			
		||||
b612.me/starmap v1.2.0/go.mod h1:InIJXA3qVeMkvkUhCV/XPchCiNcJcVYdYV8EAOGbGZY=
 | 
			
		||||
b612.me/starnet v0.1.3/go.mod h1:j/dd6BKwQK80O4gfbGYg2aYtPH76gSdgpuKboK/DwN4=
 | 
			
		||||
b612.me/starnet v0.1.5 h1:HdhUMRxTkQietBZvg9azXdFugbIcBI4e7/EjbFctyeo=
 | 
			
		||||
b612.me/starnet v0.1.5/go.mod h1:j/dd6BKwQK80O4gfbGYg2aYtPH76gSdgpuKboK/DwN4=
 | 
			
		||||
b612.me/staros v1.1.2/go.mod h1:9kNWVJWNJfs2MiWEt7X3SO+ixYKPGqus1ShTy8hpfU0=
 | 
			
		||||
b612.me/staros v1.1.4 h1:Ikh74tYMqXkDHXJHArVf1/yhLMORfwZ+q8clAKvYjrM=
 | 
			
		||||
b612.me/staros v1.1.4/go.mod h1://P/Ivz7hb/lrI+FwMh5G/T27iJ8WlWZZr3wOoPfVsU=
 | 
			
		||||
b612.me/win32api v0.0.1 h1:vLFB1xhO6pd9+zB2EyaapKB459Urv3v+C1YwgwOFEWo=
 | 
			
		||||
b612.me/win32api v0.0.1/go.mod h1:MHu0JBQjzxQ2yxpZPUBbn5un45o67eF5iWKa4Q9e0yE=
 | 
			
		||||
b612.me/wincmd v0.0.1 h1:4+RCFKHuD/JqAYsdtO6sTNKJs1nQVMQo87h6KhTJjkM=
 | 
			
		||||
b612.me/wincmd v0.0.1/go.mod h1:32xTM7qWAI7jx6qwTrig05rxejSYbSp7CX5WD7qsMxY=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 | 
			
		||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5 h1:saXMvIOKvRFwbOMicHXr0B1uwoxq9dGmLe5ExMES6c4=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
 | 
			
		||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 | 
			
		||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
							
								
								
									
										118
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,118 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/starlog"
 | 
			
		||||
	"b612.me/starnet"
 | 
			
		||||
	"b612.me/staros"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	myDir := filepath.Dir(os.Args[0])
 | 
			
		||||
	baseName := filepath.Base(os.Args[0])
 | 
			
		||||
	procs, err := staros.FindProcessByName(baseName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		starlog.Errorln(err)
 | 
			
		||||
		os.Exit(2)
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range procs {
 | 
			
		||||
		if int(v.Pid) == os.Getpid() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if len(v.Args) > 1 {
 | 
			
		||||
			starlog.Errorf("another process already run:%+v\n", v)
 | 
			
		||||
			os.Exit(3)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(os.Args) < 2 {
 | 
			
		||||
		pid, err := staros.Daemon(os.Args[0], "-f")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Println(err)
 | 
			
		||||
			os.Exit(1)
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Println("pid :", pid)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	starlog.SetLogFile(filepath.Join(myDir, "icbcauth.log"), starlog.Std, true)
 | 
			
		||||
	defer starlog.Close(starlog.Std)
 | 
			
		||||
	//sig := make(chan os.Signal)
 | 
			
		||||
	//signal.Notify(sig, os.Kill, os.Interrupt)
 | 
			
		||||
	//for {
 | 
			
		||||
	data, err := CheckNeedAuth(starlog.Std)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if data != nil {
 | 
			
		||||
		err = Auth(starlog.Std, data)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	//		return
 | 
			
		||||
	//		select {
 | 
			
		||||
	//		case <-sig:
 | 
			
		||||
	//			starlog.Infoln("Stopped By Signal")
 | 
			
		||||
	//			return
 | 
			
		||||
	//		case <-time.After(time.Second * 300):
 | 
			
		||||
	//		}
 | 
			
		||||
	//	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CheckNeedAuth(log *starlog.StarLogger) (*url.URL, error) {
 | 
			
		||||
	log.Noticeln("Checking If Need Auth")
 | 
			
		||||
	res, err := starnet.Curl(starnet.NewRequests("http://139.199.163.65/", nil, "GET",
 | 
			
		||||
		starnet.WithDisableRedirect(true)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Errorln("Checking Failed:", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if res.Location != nil {
 | 
			
		||||
		log.Warningln("Checking Finished:Need Auth,Auth Url:", res.Location.String())
 | 
			
		||||
		return res.Location, nil
 | 
			
		||||
	}
 | 
			
		||||
	log.Infoln("Checking Finished,No Need Auth")
 | 
			
		||||
	return nil, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Auth(log *starlog.StarLogger, authUrl *url.URL) error {
 | 
			
		||||
	log.Noticeln("Trying to Auth...")
 | 
			
		||||
	strUrl := "http://" + authUrl.Host + "/portallogin?" + authUrl.RawQuery
 | 
			
		||||
	log.Noticeln("Auth Url is:", strUrl)
 | 
			
		||||
	res, err := starnet.Curl(starnet.NewRequests(strUrl, nil, "GET",
 | 
			
		||||
		starnet.WithDisableRedirect(true)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Errorln("Auth Failed:", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if res.Location == nil {
 | 
			
		||||
		starlog.Errorln("Cannot Got Redirect Url")
 | 
			
		||||
		return errors.New("Cannot Got Redirect Url")
 | 
			
		||||
	}
 | 
			
		||||
	starlog.Infoln("Redirect Url is:", res.Location.String())
 | 
			
		||||
	starlog.Noticeln("Getting Cookie...")
 | 
			
		||||
	cok, err := starnet.Curl(starnet.NewRequests(res.Location.String(), nil, "GET"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Errorln("Auth Failed:", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if len(cok.RespCookies) == 0 {
 | 
			
		||||
		log.Errorln("Cannot Got Cookies")
 | 
			
		||||
		return errors.New("Get Cookie Failed")
 | 
			
		||||
	}
 | 
			
		||||
	starlog.Infoln("Got Cookie:", cok.RespCookies)
 | 
			
		||||
	starlog.Noticeln("Trying to Using Auth Url:", `http://content.icbc.com.cn/cmp/AuthSkipController.do?method=authSkip&ajaxRequest=true`)
 | 
			
		||||
	res, err = starnet.Curl(starnet.NewRequests(`http://content.icbc.com.cn/cmp/AuthSkipController.do?method=authSkip&ajaxRequest=true`,
 | 
			
		||||
		nil, "GET", starnet.WithDisableRedirect(true),
 | 
			
		||||
		starnet.WithHeader("Referer", res.Location.String()),
 | 
			
		||||
		starnet.WithCookies(cok.RespCookies)))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Errorln("Auth Failed:", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	log.Infoln("Auth Result:", res.RespHttpCode, string(res.RecvData))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										593
									
								
								vendor/b612.me/notify/client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										593
									
								
								vendor/b612.me/notify/client.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,593 @@
 | 
			
		||||
package notify
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/starcrypto"
 | 
			
		||||
	"b612.me/stario"
 | 
			
		||||
	"b612.me/starnet"
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//var nowd int64
 | 
			
		||||
type ClientCommon struct {
 | 
			
		||||
	alive                      atomic.Value
 | 
			
		||||
	status                     Status
 | 
			
		||||
	byeFromServer              bool
 | 
			
		||||
	conn                       net.Conn
 | 
			
		||||
	mu                         sync.Mutex
 | 
			
		||||
	msgID                      uint64
 | 
			
		||||
	queue                      *starnet.StarQueue
 | 
			
		||||
	stopFn                     context.CancelFunc
 | 
			
		||||
	stopCtx                    context.Context
 | 
			
		||||
	parallelNum                int
 | 
			
		||||
	maxReadTimeout             time.Duration
 | 
			
		||||
	maxWriteTimeout            time.Duration
 | 
			
		||||
	keyExchangeFn              func(c Client) error
 | 
			
		||||
	linkFns                    map[string]func(message *Message)
 | 
			
		||||
	defaultFns                 func(message *Message)
 | 
			
		||||
	msgEn                      func([]byte, []byte) []byte
 | 
			
		||||
	msgDe                      func([]byte, []byte) []byte
 | 
			
		||||
	noFinSyncMsgPool           sync.Map
 | 
			
		||||
	handshakeRsaPubKey         []byte
 | 
			
		||||
	SecretKey                  []byte
 | 
			
		||||
	noFinSyncMsgMaxKeepSeconds int
 | 
			
		||||
	lastHeartbeat              int64
 | 
			
		||||
	heartbeatPeriod            time.Duration
 | 
			
		||||
	wg                         stario.WaitGroup
 | 
			
		||||
	netType                    NetType
 | 
			
		||||
	showError                  bool
 | 
			
		||||
	skipKeyExchange            bool
 | 
			
		||||
	useHeartBeat               bool
 | 
			
		||||
	sequenceDe                 func([]byte) (interface{}, error)
 | 
			
		||||
	sequenceEn                 func(interface{}) ([]byte, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) Connect(network string, addr string) error {
 | 
			
		||||
	if c.alive.Load().(bool) {
 | 
			
		||||
		return errors.New("client already run")
 | 
			
		||||
	}
 | 
			
		||||
	c.stopCtx, c.stopFn = context.WithCancel(context.Background())
 | 
			
		||||
	c.queue = starnet.NewQueueCtx(c.stopCtx, 4)
 | 
			
		||||
	conn, err := net.Dial(network, addr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	c.alive.Store(true)
 | 
			
		||||
	c.status.Alive = true
 | 
			
		||||
	c.conn = conn
 | 
			
		||||
	if c.useHeartBeat {
 | 
			
		||||
		go c.Heartbeat()
 | 
			
		||||
	}
 | 
			
		||||
	return c.clientPostInit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) ConnectTimeout(network string, addr string, timeout time.Duration) error {
 | 
			
		||||
	if c.alive.Load().(bool) {
 | 
			
		||||
		return errors.New("client already run")
 | 
			
		||||
	}
 | 
			
		||||
	c.stopCtx, c.stopFn = context.WithCancel(context.Background())
 | 
			
		||||
	c.queue = starnet.NewQueueCtx(c.stopCtx, 4)
 | 
			
		||||
	conn, err := net.DialTimeout(network, addr, timeout)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	c.alive.Store(true)
 | 
			
		||||
	c.status.Alive = true
 | 
			
		||||
	c.conn = conn
 | 
			
		||||
	if c.useHeartBeat {
 | 
			
		||||
		go c.Heartbeat()
 | 
			
		||||
	}
 | 
			
		||||
	return c.clientPostInit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) monitorPool() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-c.stopCtx.Done():
 | 
			
		||||
			c.noFinSyncMsgPool.Range(func(k, v interface{}) bool {
 | 
			
		||||
				data := v.(WaitMsg)
 | 
			
		||||
				close(data.Reply)
 | 
			
		||||
				c.noFinSyncMsgPool.Delete(k)
 | 
			
		||||
				return true
 | 
			
		||||
			})
 | 
			
		||||
			return
 | 
			
		||||
		case <-time.After(time.Second * 30):
 | 
			
		||||
		}
 | 
			
		||||
		now := time.Now()
 | 
			
		||||
		if c.noFinSyncMsgMaxKeepSeconds > 0 {
 | 
			
		||||
			c.noFinSyncMsgPool.Range(func(k, v interface{}) bool {
 | 
			
		||||
				data := v.(WaitMsg)
 | 
			
		||||
				if data.Time.Add(time.Duration(c.noFinSyncMsgMaxKeepSeconds) * time.Second).Before(now) {
 | 
			
		||||
					close(data.Reply)
 | 
			
		||||
					c.noFinSyncMsgPool.Delete(k)
 | 
			
		||||
				}
 | 
			
		||||
				return true
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SkipExchangeKey() bool {
 | 
			
		||||
	return c.skipKeyExchange
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SetSkipExchangeKey(val bool) {
 | 
			
		||||
	c.skipKeyExchange = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) clientPostInit() error {
 | 
			
		||||
	go c.readMessage()
 | 
			
		||||
	go c.loadMessage()
 | 
			
		||||
	if !c.skipKeyExchange {
 | 
			
		||||
		err := c.keyExchangeFn(c)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			c.alive.Store(false)
 | 
			
		||||
			c.mu.Lock()
 | 
			
		||||
			c.status = Status{
 | 
			
		||||
				Alive:  false,
 | 
			
		||||
				Reason: "key exchange failed",
 | 
			
		||||
				Err:    err,
 | 
			
		||||
			}
 | 
			
		||||
			c.mu.Unlock()
 | 
			
		||||
			c.stopFn()
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func NewClient() Client {
 | 
			
		||||
	var client = ClientCommon{
 | 
			
		||||
		maxReadTimeout:     0,
 | 
			
		||||
		maxWriteTimeout:    0,
 | 
			
		||||
		sequenceEn:         encode,
 | 
			
		||||
		sequenceDe:         Decode,
 | 
			
		||||
		keyExchangeFn:      aesRsaHello,
 | 
			
		||||
		SecretKey:          defaultAesKey,
 | 
			
		||||
		handshakeRsaPubKey: defaultRsaPubKey,
 | 
			
		||||
		msgEn:              defaultMsgEn,
 | 
			
		||||
		msgDe:              defaultMsgDe,
 | 
			
		||||
	}
 | 
			
		||||
	client.alive.Store(false)
 | 
			
		||||
	//heartbeat should not controlable for user
 | 
			
		||||
	client.useHeartBeat = true
 | 
			
		||||
	client.heartbeatPeriod = time.Second * 20
 | 
			
		||||
	client.linkFns = make(map[string]func(*Message))
 | 
			
		||||
	client.defaultFns = func(message *Message) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	client.wg = stario.NewWaitGroup(0)
 | 
			
		||||
	client.stopCtx, client.stopFn = context.WithCancel(context.Background())
 | 
			
		||||
	return &client
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) Heartbeat() {
 | 
			
		||||
	failedCount := 0
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-c.stopCtx.Done():
 | 
			
		||||
			return
 | 
			
		||||
		case <-time.After(c.heartbeatPeriod):
 | 
			
		||||
		}
 | 
			
		||||
		_, err := c.sendWait(TransferMsg{
 | 
			
		||||
			ID:    10000,
 | 
			
		||||
			Key:   "heartbeat",
 | 
			
		||||
			Value: nil,
 | 
			
		||||
			Type:  MSG_SYS_WAIT,
 | 
			
		||||
		}, time.Second*5)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			c.lastHeartbeat = time.Now().Unix()
 | 
			
		||||
			failedCount = 0
 | 
			
		||||
		}
 | 
			
		||||
		failedCount++
 | 
			
		||||
		if failedCount >= 3 {
 | 
			
		||||
			//fmt.Println("heatbeat failed,stop client")
 | 
			
		||||
			c.alive.Store(false)
 | 
			
		||||
			c.mu.Lock()
 | 
			
		||||
			c.status = Status{
 | 
			
		||||
				Alive:  false,
 | 
			
		||||
				Reason: "heartbeat failed more than 3 times",
 | 
			
		||||
				Err:    errors.New("heartbeat failed more than 3 times"),
 | 
			
		||||
			}
 | 
			
		||||
			c.mu.Unlock()
 | 
			
		||||
			c.stopFn()
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) ShowError(std bool) {
 | 
			
		||||
	c.mu.Lock()
 | 
			
		||||
	c.showError = std
 | 
			
		||||
	c.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) readMessage() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-c.stopCtx.Done():
 | 
			
		||||
			c.conn.Close()
 | 
			
		||||
			return
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		data := make([]byte, 8192)
 | 
			
		||||
		if c.maxReadTimeout.Seconds() != 0 {
 | 
			
		||||
			c.conn.SetReadDeadline(time.Now().Add(c.maxReadTimeout))
 | 
			
		||||
		}
 | 
			
		||||
		readNum, err := c.conn.Read(data)
 | 
			
		||||
		if err == os.ErrDeadlineExceeded {
 | 
			
		||||
			if readNum != 0 {
 | 
			
		||||
				c.queue.ParseMessage(data[:readNum], "b612")
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if c.showError {
 | 
			
		||||
				fmt.Println("client read error", err)
 | 
			
		||||
			}
 | 
			
		||||
			c.alive.Store(false)
 | 
			
		||||
			c.mu.Lock()
 | 
			
		||||
			c.status = Status{
 | 
			
		||||
				Alive:  false,
 | 
			
		||||
				Reason: "client read error",
 | 
			
		||||
				Err:    err,
 | 
			
		||||
			}
 | 
			
		||||
			c.mu.Unlock()
 | 
			
		||||
			c.stopFn()
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		c.queue.ParseMessage(data[:readNum], "b612")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) sayGoodBye() error {
 | 
			
		||||
	_, err := c.sendWait(TransferMsg{
 | 
			
		||||
		ID:    10010,
 | 
			
		||||
		Key:   "bye",
 | 
			
		||||
		Value: nil,
 | 
			
		||||
		Type:  MSG_SYS_WAIT,
 | 
			
		||||
	}, time.Second*3)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) loadMessage() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-c.stopCtx.Done():
 | 
			
		||||
			//say goodbye
 | 
			
		||||
			if !c.byeFromServer {
 | 
			
		||||
				c.sayGoodBye()
 | 
			
		||||
			}
 | 
			
		||||
			c.conn.Close()
 | 
			
		||||
			return
 | 
			
		||||
		case data, ok := <-c.queue.RestoreChan():
 | 
			
		||||
			if !ok {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			c.wg.Add(1)
 | 
			
		||||
			go func(data starnet.MsgQueue) {
 | 
			
		||||
				defer c.wg.Done()
 | 
			
		||||
				//fmt.Println("c received:", float64(time.Now().UnixNano()-nowd)/1000000)
 | 
			
		||||
				now := time.Now()
 | 
			
		||||
				//transfer to Msg
 | 
			
		||||
				msg, err := c.sequenceDe(c.msgDe(c.SecretKey, data.Msg))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					if c.showError {
 | 
			
		||||
						fmt.Println("client decode data error", err)
 | 
			
		||||
					}
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				message := Message{
 | 
			
		||||
					ServerConn:  c,
 | 
			
		||||
					TransferMsg: msg.(TransferMsg),
 | 
			
		||||
					NetType:     NET_CLIENT,
 | 
			
		||||
				}
 | 
			
		||||
				message.Time = now
 | 
			
		||||
				c.dispatchMsg(message)
 | 
			
		||||
			}(data)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) dispatchMsg(message Message) {
 | 
			
		||||
	switch message.TransferMsg.Type {
 | 
			
		||||
	case MSG_SYS_WAIT:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case MSG_SYS:
 | 
			
		||||
		c.sysMsg(message)
 | 
			
		||||
		return
 | 
			
		||||
	case MSG_KEY_CHANGE:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case MSG_SYS_REPLY:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case MSG_SYNC_REPLY:
 | 
			
		||||
		data, ok := c.noFinSyncMsgPool.Load(message.ID)
 | 
			
		||||
		if ok {
 | 
			
		||||
			wait := data.(WaitMsg)
 | 
			
		||||
			wait.Reply <- message
 | 
			
		||||
			c.noFinSyncMsgPool.Delete(message.ID)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
		//fallthrough
 | 
			
		||||
	default:
 | 
			
		||||
	}
 | 
			
		||||
	callFn := func(fn func(*Message)) {
 | 
			
		||||
		fn(&message)
 | 
			
		||||
	}
 | 
			
		||||
	fn, ok := c.linkFns[message.Key]
 | 
			
		||||
	if ok {
 | 
			
		||||
		callFn(fn)
 | 
			
		||||
	}
 | 
			
		||||
	if c.defaultFns != nil {
 | 
			
		||||
		callFn(c.defaultFns)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) sysMsg(message Message) {
 | 
			
		||||
	switch message.Key {
 | 
			
		||||
	case "bye":
 | 
			
		||||
		if message.TransferMsg.Type == MSG_SYS_WAIT {
 | 
			
		||||
			//fmt.Println("recv stop signal from server")
 | 
			
		||||
			c.byeFromServer = true
 | 
			
		||||
			message.Reply(nil)
 | 
			
		||||
		}
 | 
			
		||||
		c.alive.Store(false)
 | 
			
		||||
		c.mu.Lock()
 | 
			
		||||
		c.status = Status{
 | 
			
		||||
			Alive:  false,
 | 
			
		||||
			Reason: "recv stop signal from server",
 | 
			
		||||
			Err:    nil,
 | 
			
		||||
		}
 | 
			
		||||
		c.mu.Unlock()
 | 
			
		||||
		c.stopFn()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SetDefaultLink(fn func(message *Message)) {
 | 
			
		||||
	c.defaultFns = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SetLink(key string, fn func(*Message)) {
 | 
			
		||||
	c.mu.Lock()
 | 
			
		||||
	defer c.mu.Unlock()
 | 
			
		||||
	c.linkFns[key] = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) send(msg TransferMsg) (WaitMsg, error) {
 | 
			
		||||
	var wait WaitMsg
 | 
			
		||||
	if msg.Type != MSG_SYNC_REPLY && msg.Type != MSG_KEY_CHANGE && msg.Type != MSG_SYS_REPLY || msg.ID == 0 {
 | 
			
		||||
		msg.ID = atomic.AddUint64(&c.msgID, 1)
 | 
			
		||||
	}
 | 
			
		||||
	data, err := c.sequenceEn(msg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return WaitMsg{}, err
 | 
			
		||||
	}
 | 
			
		||||
	data = c.msgEn(c.SecretKey, data)
 | 
			
		||||
	data = c.queue.BuildMessage(data)
 | 
			
		||||
	if c.maxWriteTimeout.Seconds() != 0 {
 | 
			
		||||
		c.conn.SetWriteDeadline(time.Now().Add(c.maxWriteTimeout))
 | 
			
		||||
	}
 | 
			
		||||
	_, err = c.conn.Write(data)
 | 
			
		||||
	if err == nil && (msg.Type == MSG_SYNC_ASK || msg.Type == MSG_KEY_CHANGE || msg.Type == MSG_SYS_WAIT) {
 | 
			
		||||
		wait.Time = time.Now()
 | 
			
		||||
		wait.TransferMsg = msg
 | 
			
		||||
		wait.Reply = make(chan Message, 1)
 | 
			
		||||
		c.noFinSyncMsgPool.Store(msg.ID, wait)
 | 
			
		||||
	}
 | 
			
		||||
	return wait, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) Send(key string, value MsgVal) error {
 | 
			
		||||
	_, err := c.send(TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: value,
 | 
			
		||||
		Type:  MSG_ASYNC,
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) sendWait(msg TransferMsg, timeout time.Duration) (Message, error) {
 | 
			
		||||
	data, err := c.send(msg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Message{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if timeout.Seconds() == 0 {
 | 
			
		||||
		msg, ok := <-data.Reply
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return msg, os.ErrInvalid
 | 
			
		||||
		}
 | 
			
		||||
		return msg, nil
 | 
			
		||||
	}
 | 
			
		||||
	select {
 | 
			
		||||
	case <-time.After(timeout):
 | 
			
		||||
		close(data.Reply)
 | 
			
		||||
		c.noFinSyncMsgPool.Delete(data.TransferMsg.ID)
 | 
			
		||||
		return Message{}, os.ErrDeadlineExceeded
 | 
			
		||||
	case <-c.stopCtx.Done():
 | 
			
		||||
		return Message{}, errors.New("Service shutdown")
 | 
			
		||||
	case msg, ok := <-data.Reply:
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return msg, os.ErrInvalid
 | 
			
		||||
		}
 | 
			
		||||
		return msg, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) sendCtx(msg TransferMsg, ctx context.Context) (Message, error) {
 | 
			
		||||
	data, err := c.send(msg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Message{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if ctx == nil {
 | 
			
		||||
		ctx = context.Background()
 | 
			
		||||
	}
 | 
			
		||||
	select {
 | 
			
		||||
	case <-ctx.Done():
 | 
			
		||||
		close(data.Reply)
 | 
			
		||||
		c.noFinSyncMsgPool.Delete(data.TransferMsg.ID)
 | 
			
		||||
		return Message{}, os.ErrDeadlineExceeded
 | 
			
		||||
	case <-c.stopCtx.Done():
 | 
			
		||||
		return Message{}, errors.New("Service shutdown")
 | 
			
		||||
	case msg, ok := <-data.Reply:
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return msg, os.ErrInvalid
 | 
			
		||||
		}
 | 
			
		||||
		return msg, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SendObjCtx(ctx context.Context, key string, val interface{}) (Message, error) {
 | 
			
		||||
	data, err := c.sequenceEn(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Message{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return c.sendCtx(TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: data,
 | 
			
		||||
		Type:  MSG_SYNC_ASK,
 | 
			
		||||
	}, ctx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SendObj(key string, val interface{}) error {
 | 
			
		||||
	data, err := encode(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, err = c.send(TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: data,
 | 
			
		||||
		Type:  MSG_ASYNC,
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SendCtx(ctx context.Context, key string, value MsgVal) (Message, error) {
 | 
			
		||||
	return c.sendCtx(TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: value,
 | 
			
		||||
		Type:  MSG_SYNC_ASK,
 | 
			
		||||
	}, ctx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SendWait(key string, value MsgVal, timeout time.Duration) (Message, error) {
 | 
			
		||||
	return c.sendWait(TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: value,
 | 
			
		||||
		Type:  MSG_SYNC_ASK,
 | 
			
		||||
	}, timeout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) SendWaitObj(key string, value interface{}, timeout time.Duration) (Message, error) {
 | 
			
		||||
	data, err := c.sequenceEn(value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Message{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return c.SendWait(key, data, timeout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) Reply(m Message, value MsgVal) error {
 | 
			
		||||
	return m.Reply(value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) ExchangeKey(newKey []byte) error {
 | 
			
		||||
	newSendKey, err := starcrypto.RSAEncrypt(newKey, c.handshakeRsaPubKey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	data, err := c.sendWait(TransferMsg{
 | 
			
		||||
		ID:    19961127,
 | 
			
		||||
		Key:   "sirius",
 | 
			
		||||
		Value: newSendKey,
 | 
			
		||||
		Type:  MSG_KEY_CHANGE,
 | 
			
		||||
	}, time.Second*10)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if string(data.Value) != "success" {
 | 
			
		||||
		return errors.New("cannot exchange new aes-key")
 | 
			
		||||
	}
 | 
			
		||||
	c.SecretKey = newKey
 | 
			
		||||
	time.Sleep(time.Millisecond * 100)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func aesRsaHello(c Client) error {
 | 
			
		||||
	newAesKey := []byte(fmt.Sprintf("%d%d%d%s", time.Now().UnixNano(), rand.Int63(), rand.Int63(), "b612.me"))
 | 
			
		||||
	newAesKey = []byte(starcrypto.Md5Str(newAesKey))
 | 
			
		||||
	return c.ExchangeKey(newAesKey)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) GetMsgEn() func([]byte, []byte) []byte {
 | 
			
		||||
	return c.msgEn
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) SetMsgEn(fn func([]byte, []byte) []byte) {
 | 
			
		||||
	c.msgEn = fn
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) GetMsgDe() func([]byte, []byte) []byte {
 | 
			
		||||
	return c.msgDe
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) SetMsgDe(fn func([]byte, []byte) []byte) {
 | 
			
		||||
	c.msgDe = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) HeartbeatPeroid() time.Duration {
 | 
			
		||||
	return c.heartbeatPeriod
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) SetHeartbeatPeroid(duration time.Duration) {
 | 
			
		||||
	c.heartbeatPeriod = duration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) GetSecretKey() []byte {
 | 
			
		||||
	return c.SecretKey
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) SetSecretKey(key []byte) {
 | 
			
		||||
	c.SecretKey = key
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) RsaPubKey() []byte {
 | 
			
		||||
	return c.handshakeRsaPubKey
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) SetRsaPubKey(key []byte) {
 | 
			
		||||
	c.handshakeRsaPubKey = key
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) Stop() error {
 | 
			
		||||
	if !c.alive.Load().(bool) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	c.alive.Store(false)
 | 
			
		||||
	c.mu.Lock()
 | 
			
		||||
	c.status = Status{
 | 
			
		||||
		Alive:  false,
 | 
			
		||||
		Reason: "recv stop signal from user",
 | 
			
		||||
		Err:    nil,
 | 
			
		||||
	}
 | 
			
		||||
	c.mu.Unlock()
 | 
			
		||||
	c.stopFn()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) StopMonitorChan() <-chan struct{} {
 | 
			
		||||
	return c.stopCtx.Done()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) Status() Status {
 | 
			
		||||
	return c.status
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientCommon) GetSequenceEn() func(interface{}) ([]byte, error) {
 | 
			
		||||
	return c.sequenceEn
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) SetSequenceEn(fn func(interface{}) ([]byte, error)) {
 | 
			
		||||
	c.sequenceEn = fn
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) GetSequenceDe() func([]byte) (interface{}, error) {
 | 
			
		||||
	return c.sequenceDe
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientCommon) SetSequenceDe(fn func([]byte) (interface{}, error)) {
 | 
			
		||||
	c.sequenceDe = fn
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								vendor/b612.me/notify/clienttype.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/b612.me/notify/clienttype.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
package notify
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Client interface {
 | 
			
		||||
	SetDefaultLink(func(message *Message))
 | 
			
		||||
	SetLink(string, func(*Message))
 | 
			
		||||
	send(msg TransferMsg) (WaitMsg, error)
 | 
			
		||||
	sendWait(msg TransferMsg, timeout time.Duration) (Message, error)
 | 
			
		||||
	Send(key string, value MsgVal) error
 | 
			
		||||
	SendWait(key string, value MsgVal, timeout time.Duration) (Message, error)
 | 
			
		||||
	SendWaitObj(key string, value interface{}, timeout time.Duration) (Message, error)
 | 
			
		||||
	SendCtx(ctx context.Context, key string, value MsgVal) (Message, error)
 | 
			
		||||
	Reply(m Message, value MsgVal) error
 | 
			
		||||
	ExchangeKey(newKey []byte) error
 | 
			
		||||
	Connect(network string, addr string) error
 | 
			
		||||
	ConnectTimeout(network string, addr string, timeout time.Duration) error
 | 
			
		||||
	SkipExchangeKey() bool
 | 
			
		||||
	SetSkipExchangeKey(bool)
 | 
			
		||||
 | 
			
		||||
	GetMsgEn() func([]byte, []byte) []byte
 | 
			
		||||
	SetMsgEn(func([]byte, []byte) []byte)
 | 
			
		||||
	GetMsgDe() func([]byte, []byte) []byte
 | 
			
		||||
	SetMsgDe(func([]byte, []byte) []byte)
 | 
			
		||||
 | 
			
		||||
	Heartbeat()
 | 
			
		||||
	HeartbeatPeroid() time.Duration
 | 
			
		||||
	SetHeartbeatPeroid(duration time.Duration)
 | 
			
		||||
 | 
			
		||||
	GetSecretKey() []byte
 | 
			
		||||
	SetSecretKey(key []byte)
 | 
			
		||||
	RsaPubKey() []byte
 | 
			
		||||
	SetRsaPubKey([]byte)
 | 
			
		||||
 | 
			
		||||
	Stop() error
 | 
			
		||||
	StopMonitorChan() <-chan struct{}
 | 
			
		||||
	Status() Status
 | 
			
		||||
	ShowError(bool)
 | 
			
		||||
 | 
			
		||||
	GetSequenceEn() func(interface{}) ([]byte, error)
 | 
			
		||||
	SetSequenceEn(func(interface{}) ([]byte, error))
 | 
			
		||||
	GetSequenceDe() func([]byte) (interface{}, error)
 | 
			
		||||
	SetSequenceDe(func([]byte) (interface{}, error))
 | 
			
		||||
	SendObjCtx(ctx context.Context, key string, val interface{}) (Message, error)
 | 
			
		||||
	SendObj(key string, val interface{}) error
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								vendor/b612.me/notify/default.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								vendor/b612.me/notify/default.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
package notify
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/starcrypto"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var defaultRsaKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
 | 
			
		||||
MIIJKAIBAAKCAgEAxmeMqr9yfJFKZn26oe/HvC7bZXNLC9Nk55AuTkb4XuIoqXDb
 | 
			
		||||
AJD2Y/p167oJLKIqL3edcj7h+oTfn6s79vxT0ZCEf37ILU0G+scRzVwYHiLMwOUC
 | 
			
		||||
bS2o4Xor3zqUi9f1piJBvoBNh8RKKtsmJW6VQZdiUGJHbgX4MdOdtf/6TvxZMwSX
 | 
			
		||||
U+PRSCAjy04A31Zi7DEWUWJPyqmHeu++PxXU5lvoMdCGDqpcF2j2uO7oJJUww01M
 | 
			
		||||
3F5FtTElMrK4/P9gD4kP7NiPhOfVPEfBsYT/DSSjvqNZJZuWnxu+cDxE7J/sBvdp
 | 
			
		||||
eNRLhqzdmMYagZFuUmVrz8QmsD6jKHgydW+r7irllvb8WJPK/RIMif+4Rg7rDKFb
 | 
			
		||||
j8+ZQ3HZ/gKELoRSyb3zL6RC2qlGLjC1tdeN7TNTinCv092y39T8jIARJ7tpfePh
 | 
			
		||||
NBxsBdxfXbCAzHYZIHufI9Zlsc+felQwanlDhq+q8YLcnKHvNKYVyCf/upExpAiA
 | 
			
		||||
rr88y/KbeKes0KorKkwMBnGUMTothWM25wHozcurixNvP4UMWX7LWD7vOZZuNDQN
 | 
			
		||||
utZYeTwdsniI3mTO9vlPWEK8JTfxBU7x9SePUMJNDyjfDUJM8C2DOlyhGNPkgazO
 | 
			
		||||
GdliH87tHkEy/7jJnGclgKmciiVPgwHfFx9GGoBHEfvmAoGGrk4qNbjm7JECAwEA
 | 
			
		||||
AQKCAgBYzHe05ELFZfG6tYMWf08R9pbTbSqlfFOpIGrZNgJr1SUF0TDzq+3bCXpF
 | 
			
		||||
qtn4VAw1en/JZkOV8Gp1+Bm6jWymWtwyg/fr7pG1I+vf0dwpgMHLg7P2UX1IjXmd
 | 
			
		||||
S4a4oEuds69hJ+OLZFsdm0ATeM7ssGicOaBmqd1Pz7rCfnL1bxQtNVzVex1r/paG
 | 
			
		||||
o77YNr3HoKCwhCPaPM4aQ7sOWSMUhwYBZabaYX0eLShf1O2pkexlPO+tobPpSLmx
 | 
			
		||||
WzRYZ6QC0AGEq9hwT6KsfCFA5pmQtFllNY7suhpL1AsECLWAgoMNCyb1oW68NBpq
 | 
			
		||||
CiBK5WBPGH2MW+pE74Pu1P0gen6kLGnApKQjprE1aGuR+xkZe3uEnXwSryU9TXki
 | 
			
		||||
wINTEMsX8dkmofFqaJhUwSubrb+t7gvv9E9ZZe0X6UgKzAVVqvh4z1pP8VT+xHpu
 | 
			
		||||
pW7SR8n9cFddaEPUijSb1rSpJrNzfJJ+G7yrB7Cw2kBgQ07vzD3z/3kA9cwFevLS
 | 
			
		||||
mv3l3OQuB6y9c+AG3cX5WGAt/BVOLjimj9qJt+YglG0SwG31U0PUnnx6QVz/UtJm
 | 
			
		||||
CbJQ2TpJd+mk0HyuMU+eycp7BWF3PMN+SE4QgKCKWnhsLeAd3gcvifsbLOYE1OPg
 | 
			
		||||
wv1tqyJy0VsJiSn6Ub6Qq0kPLwCLlQTnLWk5mIhnRpHYufTSwQKCAQEA4gS4FKPU
 | 
			
		||||
tAcQ82dEYW4OjGfhNWrjFpF+A8K5zufleQWcgzQ3fQho13zH0vZobukfkEVlVxla
 | 
			
		||||
OIVk7ZgNA4mCSFrATjIx3RMqzrAUvTte0O4wkjYgCwVvTdS1W8nvRLKgugLygyoo
 | 
			
		||||
r+MLW5IT3eNMK/2fZbftNlAkbc7NCo3c2tS6MXFgjx5JUuzChOY73Kp4p5KS38L5
 | 
			
		||||
wRRiI8KTIKjBjMZ5q/l8VLKX89bKOCaWibmItoXY6QMbIjargb7YLp3X6uGEyGIu
 | 
			
		||||
VhPbQ80/+OC2ZqIvDecp4PYnJNZFeqfjyfhJCNqDjBKYwIscBLMU/Wf9OY258OR4
 | 
			
		||||
snQaerN1M0h9lQKCAQEA4LkZIRLLw+8bIVM+7VXxFwOAGy+MH35tvuNIToItAoUh
 | 
			
		||||
zjL5LG34PjID8J0DPyP8VRVanak1EcxF0aTEkvnt2f2RAVsW89ytcn8Lybb12Ae8
 | 
			
		||||
ia2ZWuIM+J40nuKOGPs3lJ9HqdPWmZYWsWKxFJmYBBnwD6CADYqhqambQn0HeaYl
 | 
			
		||||
/WUD7blLYg+4Kk1mt9/hIw93jTWP/86O2H0ia+AhYPTqyvVXfIXKhat6NlOYksGf
 | 
			
		||||
Hdv+aCC8Ukg6FyEgiNc/rFn0MWPnEX+cM1AwubviHIBhV8QWILLBTjupwsEBZVah
 | 
			
		||||
60ftH+HRUCmEeOpI7jyzIlfEUNLoBHfswKMhMPtcDQKCAQEA0JFkQX+xn/PJW6PX
 | 
			
		||||
AUWrXTvbIg0hw8i9DcFa76klJBnehWDhN5tUDE5Uo8PJOVgdTWgMjWSS0geezHX8
 | 
			
		||||
xF/XfudoAIDnbMfsP9FTQhCQfaLf5XzW8vSv8pWwSiS9jJp+IUjo+8siwrR03aqe
 | 
			
		||||
dKr0tr+ToS0qVG1+QGqO4gdpX/LgYxHp9ggPx9s94aAIa6hQMOrcaGqnSNqDedZr
 | 
			
		||||
KL8x5LOewek3J32rJVP3Rfut/SfeFfjL4rKADoF+oPs4yUPVZSV4/+VCNyKZuyaj
 | 
			
		||||
uwm6qFlPrLe9+J+OHbsxYG+fj9hzpRzoOZFLrppwX5HWc8XLcpnrlXVwP9VOPh5u
 | 
			
		||||
r8VcRQKCAQAJFHGHfJLvH8Ig3pQ0UryjCWkrsAghXaJhjB1nzqqy514uTrDysp7N
 | 
			
		||||
JIg0OKPg8TtI1MwMgsG6Ll7D0bx/k8mgfTZWr6+FuuznK2r2g4X7bJSZm4IOwgN0
 | 
			
		||||
KDBIGy9SoxPj1Wu32O9a1U2lbS9qfao+wC2K9Bk4ctmFWW0Eiri6mZP/YQ1/lXUO
 | 
			
		||||
SURPsUDtPQaDvCRAeGGRHG95H9U8NpoiqMKz4KXgSiecrwkJGOeZRml/c1wcKPZy
 | 
			
		||||
/KgcNyJxZQEVnazYMgksE9Pj3uGZH5ZLQISuXyXlvFNDLfX2AIZl6dIxB371QtKK
 | 
			
		||||
QqMvn4fC2IEEajdsbJkjVRUj03OL3xwhAoIBAAfMhDSvBbDkGTaXnNMjPPSbswqK
 | 
			
		||||
qcSRhSG27mjs1dDNBKuFbz6TkIOp4nxjuS9Zp19fErXlAE9mF5yXSmuiAkZmWfhs
 | 
			
		||||
HKpWIdjFJK1EqSfcINe2YuoyUIulz9oG7ObRHD4D8jSPjA8Ete+XsBHGyOtUl09u
 | 
			
		||||
X4u9uClhqjK+r1Tno2vw5yF6ZxfQtdWuL4W0UL1S8E+VO7vjTjNOYvgjAIpAM/gW
 | 
			
		||||
sqjA2Qw52UZqhhLXoTfRvtJilxlXXhIRJSsnUoGiYVCQ/upjqJCClEvJfIWdGY/U
 | 
			
		||||
I2CbFrwJcNvOG1lUsSM55JUmbrSWVPfo7yq2k9GCuFxOy2n/SVlvlQUcNkA=
 | 
			
		||||
-----END RSA PRIVATE KEY-----`)
 | 
			
		||||
 | 
			
		||||
var defaultRsaPubKey = []byte(`-----BEGIN PUBLIC KEY-----
 | 
			
		||||
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxmeMqr9yfJFKZn26oe/H
 | 
			
		||||
vC7bZXNLC9Nk55AuTkb4XuIoqXDbAJD2Y/p167oJLKIqL3edcj7h+oTfn6s79vxT
 | 
			
		||||
0ZCEf37ILU0G+scRzVwYHiLMwOUCbS2o4Xor3zqUi9f1piJBvoBNh8RKKtsmJW6V
 | 
			
		||||
QZdiUGJHbgX4MdOdtf/6TvxZMwSXU+PRSCAjy04A31Zi7DEWUWJPyqmHeu++PxXU
 | 
			
		||||
5lvoMdCGDqpcF2j2uO7oJJUww01M3F5FtTElMrK4/P9gD4kP7NiPhOfVPEfBsYT/
 | 
			
		||||
DSSjvqNZJZuWnxu+cDxE7J/sBvdpeNRLhqzdmMYagZFuUmVrz8QmsD6jKHgydW+r
 | 
			
		||||
7irllvb8WJPK/RIMif+4Rg7rDKFbj8+ZQ3HZ/gKELoRSyb3zL6RC2qlGLjC1tdeN
 | 
			
		||||
7TNTinCv092y39T8jIARJ7tpfePhNBxsBdxfXbCAzHYZIHufI9Zlsc+felQwanlD
 | 
			
		||||
hq+q8YLcnKHvNKYVyCf/upExpAiArr88y/KbeKes0KorKkwMBnGUMTothWM25wHo
 | 
			
		||||
zcurixNvP4UMWX7LWD7vOZZuNDQNutZYeTwdsniI3mTO9vlPWEK8JTfxBU7x9SeP
 | 
			
		||||
UMJNDyjfDUJM8C2DOlyhGNPkgazOGdliH87tHkEy/7jJnGclgKmciiVPgwHfFx9G
 | 
			
		||||
GoBHEfvmAoGGrk4qNbjm7JECAwEAAQ==
 | 
			
		||||
-----END PUBLIC KEY-----`)
 | 
			
		||||
 | 
			
		||||
var defaultAesKey = []byte{0x19, 0x96, 0x11, 0x27, 228, 187, 187, 231, 142, 137, 230, 179, 189, 229, 184, 133}
 | 
			
		||||
 | 
			
		||||
func defaultMsgEn(key []byte, d []byte) []byte {
 | 
			
		||||
	return starcrypto.AesEncryptCFB(d, key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func defaultMsgDe(key []byte, d []byte) []byte {
 | 
			
		||||
	return starcrypto.AesDecryptCFB(d, key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	Register(TransferMsg{})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										472
									
								
								vendor/b612.me/notify/msg.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										472
									
								
								vendor/b612.me/notify/msg.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,472 @@
 | 
			
		||||
package notify
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/starcrypto"
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	MSG_SYS MessageType = iota
 | 
			
		||||
	MSG_SYS_WAIT
 | 
			
		||||
	MSG_SYS_REPLY
 | 
			
		||||
	MSG_KEY_CHANGE
 | 
			
		||||
	MSG_ASYNC
 | 
			
		||||
	MSG_SYNC_ASK
 | 
			
		||||
	MSG_SYNC_REPLY
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type MessageType uint8
 | 
			
		||||
 | 
			
		||||
type NetType uint8
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	NET_SERVER NetType = iota
 | 
			
		||||
	NET_CLIENT
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type MsgVal []byte
 | 
			
		||||
type TransferMsg struct {
 | 
			
		||||
	ID    uint64
 | 
			
		||||
	Key   string
 | 
			
		||||
	Value MsgVal
 | 
			
		||||
	Type  MessageType
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Message struct {
 | 
			
		||||
	NetType
 | 
			
		||||
	ClientConn *ClientConn
 | 
			
		||||
	ServerConn Client
 | 
			
		||||
	TransferMsg
 | 
			
		||||
	Time time.Time
 | 
			
		||||
	sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type WaitMsg struct {
 | 
			
		||||
	TransferMsg
 | 
			
		||||
	Time  time.Time
 | 
			
		||||
	Reply chan Message
 | 
			
		||||
	//Ctx   context.Context
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Message) Reply(value MsgVal) (err error) {
 | 
			
		||||
	reply := TransferMsg{
 | 
			
		||||
		ID:    m.ID,
 | 
			
		||||
		Key:   m.Key,
 | 
			
		||||
		Value: value,
 | 
			
		||||
		Type:  m.Type,
 | 
			
		||||
	}
 | 
			
		||||
	if reply.Type == MSG_SYNC_ASK {
 | 
			
		||||
		reply.Type = MSG_SYNC_REPLY
 | 
			
		||||
	}
 | 
			
		||||
	if reply.Type == MSG_SYS_WAIT {
 | 
			
		||||
		reply.Type = MSG_SYS_REPLY
 | 
			
		||||
	}
 | 
			
		||||
	if m.NetType == NET_SERVER {
 | 
			
		||||
		_, err = m.ClientConn.server.send(m.ClientConn, reply)
 | 
			
		||||
	}
 | 
			
		||||
	if m.NetType == NET_CLIENT {
 | 
			
		||||
		_, err = m.ServerConn.send(reply)
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *Message) ReplyObj(value interface{}) (err error) {
 | 
			
		||||
	data, err := encode(value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return m.Reply(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ClientConn struct {
 | 
			
		||||
	alive           atomic.Value
 | 
			
		||||
	status          Status
 | 
			
		||||
	ClientID        string
 | 
			
		||||
	ClientAddr      net.Addr
 | 
			
		||||
	tuConn          net.Conn
 | 
			
		||||
	server          Server
 | 
			
		||||
	stopFn          context.CancelFunc
 | 
			
		||||
	stopCtx         context.Context
 | 
			
		||||
	maxReadTimeout  time.Duration
 | 
			
		||||
	maxWriteTimeout time.Duration
 | 
			
		||||
	msgEn           func([]byte, []byte) []byte
 | 
			
		||||
	msgDe           func([]byte, []byte) []byte
 | 
			
		||||
	handshakeRsaKey []byte
 | 
			
		||||
	SecretKey       []byte
 | 
			
		||||
	lastHeartBeat   int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Status struct {
 | 
			
		||||
	Alive  bool
 | 
			
		||||
	Reason string
 | 
			
		||||
	Err    error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) readTUMessage() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-c.stopCtx.Done():
 | 
			
		||||
			c.tuConn.Close()
 | 
			
		||||
			c.server.removeClient(c)
 | 
			
		||||
			return
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		if c.maxReadTimeout.Seconds() > 0 {
 | 
			
		||||
			c.tuConn.SetReadDeadline(time.Now().Add(c.maxReadTimeout))
 | 
			
		||||
		}
 | 
			
		||||
		data := make([]byte, 8192)
 | 
			
		||||
		num, err := c.tuConn.Read(data)
 | 
			
		||||
		if err == os.ErrDeadlineExceeded {
 | 
			
		||||
			if num != 0 {
 | 
			
		||||
				c.server.pushMessage(data[:num], c.ClientID)
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			//conn is broke
 | 
			
		||||
			c.alive.Store(false)
 | 
			
		||||
			c.status = Status{
 | 
			
		||||
				Alive:  false,
 | 
			
		||||
				Reason: "read error",
 | 
			
		||||
				Err:    err,
 | 
			
		||||
			}
 | 
			
		||||
			c.stopFn()
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		c.server.pushMessage(data[:num], c.ClientID)
 | 
			
		||||
		//fmt.Println("finished:", float64(time.Now().UnixNano()-nowd)/1000000)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) rsaDecode(message Message) {
 | 
			
		||||
	unknownKey := message.Value
 | 
			
		||||
	data, err := starcrypto.RSADecrypt(unknownKey, c.handshakeRsaKey, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println(err)
 | 
			
		||||
		message.Reply([]byte("failed"))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	//fmt.Println("aes-key changed to", string(data))
 | 
			
		||||
	message.Reply([]byte("success"))
 | 
			
		||||
	c.SecretKey = data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) sayGoodByeForTU() error {
 | 
			
		||||
	_, err := c.server.sendWait(c, TransferMsg{
 | 
			
		||||
		ID:    10010,
 | 
			
		||||
		Key:   "bye",
 | 
			
		||||
		Value: nil,
 | 
			
		||||
		Type:  MSG_SYS_WAIT,
 | 
			
		||||
	}, time.Second*3)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) GetSecretKey() []byte {
 | 
			
		||||
	return c.SecretKey
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientConn) SetSecretKey(key []byte) {
 | 
			
		||||
	c.SecretKey = key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) GetMsgEn() func([]byte, []byte) []byte {
 | 
			
		||||
	return c.msgEn
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientConn) SetMsgEn(fn func([]byte, []byte) []byte) {
 | 
			
		||||
	c.msgEn = fn
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientConn) GetMsgDe() func([]byte, []byte) []byte {
 | 
			
		||||
	return c.msgDe
 | 
			
		||||
}
 | 
			
		||||
func (c *ClientConn) SetMsgDe(fn func([]byte, []byte) []byte) {
 | 
			
		||||
	c.msgDe = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) StopMonitorChan() <-chan struct{} {
 | 
			
		||||
	return c.stopCtx.Done()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) Status() Status {
 | 
			
		||||
	return c.status
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) Server() Server {
 | 
			
		||||
	return c.server
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *ClientConn) GetRemoteAddr() net.Addr {
 | 
			
		||||
	return c.ClientAddr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToClearString() string {
 | 
			
		||||
	return string(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToInterface() (interface{}, error) {
 | 
			
		||||
	return Decode(m)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToInterface() interface{} {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToString() (string, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(string); !ok {
 | 
			
		||||
		return "", errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToString() string {
 | 
			
		||||
	inf, err := m.ToString()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToInt32() (int32, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(int32); !ok {
 | 
			
		||||
		return 0, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToInt32() int32 {
 | 
			
		||||
	inf, err := m.ToInt32()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToInt() (int, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(int); !ok {
 | 
			
		||||
		return 0, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToInt() int {
 | 
			
		||||
	inf, err := m.ToInt()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToUint64() (uint64, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(uint64); !ok {
 | 
			
		||||
		return 0, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToUint64() uint64 {
 | 
			
		||||
	inf, err := m.ToUint64()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToUint32() (uint32, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(uint32); !ok {
 | 
			
		||||
		return 0, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToUint32() uint32 {
 | 
			
		||||
	inf, err := m.ToUint32()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToUint() (uint, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(uint); !ok {
 | 
			
		||||
		return 0, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToUint() uint {
 | 
			
		||||
	inf, err := m.ToUint()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToBool() (bool, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(bool); !ok {
 | 
			
		||||
		return false, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToBool() bool {
 | 
			
		||||
	inf, err := m.ToBool()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToFloat64() (float64, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(float64); !ok {
 | 
			
		||||
		return 0, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToFloat64() float64 {
 | 
			
		||||
	inf, err := m.ToFloat64()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
func (m MsgVal) ToFloat32() (float32, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.(float32); !ok {
 | 
			
		||||
		return 0, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToFloat32() float32 {
 | 
			
		||||
	inf, err := m.ToFloat32()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToSliceString() ([]string, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []string{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.([]string); !ok {
 | 
			
		||||
		return []string{}, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToSliceString() []string {
 | 
			
		||||
	inf, err := m.ToSliceString()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToSliceInt64() ([]int64, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []int64{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.([]int64); !ok {
 | 
			
		||||
		return []int64{}, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToSliceInt64() []int64 {
 | 
			
		||||
	inf, err := m.ToSliceInt64()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) ToSliceFloat64() ([]float64, error) {
 | 
			
		||||
	inf, err := m.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []float64{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if data, ok := inf.([]float64); !ok {
 | 
			
		||||
		return []float64{}, errors.New("source data not match target type")
 | 
			
		||||
	} else {
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m MsgVal) MustToSliceFloat64() []float64 {
 | 
			
		||||
	inf, err := m.ToSliceFloat64()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return inf
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ToMsgVal(val interface{}) (MsgVal, error) {
 | 
			
		||||
	return Encode(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MustToMsgVal(val interface{}) MsgVal {
 | 
			
		||||
	d, err := ToMsgVal(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return d
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								vendor/b612.me/notify/serialization.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/b612.me/notify/serialization.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
package notify
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/gob"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Register(data interface{}) {
 | 
			
		||||
	gob.Register(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RegisterAll(data []interface{}) {
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		gob.Register(v)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func encode(src interface{}) ([]byte, error) {
 | 
			
		||||
	var buf bytes.Buffer
 | 
			
		||||
	enc := gob.NewEncoder(&buf)
 | 
			
		||||
	err := enc.Encode(&src)
 | 
			
		||||
	return buf.Bytes(), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Encode(src interface{}) ([]byte, error) {
 | 
			
		||||
	return encode(src)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Decode(src []byte) (interface{}, error) {
 | 
			
		||||
	dec := gob.NewDecoder(bytes.NewReader(src))
 | 
			
		||||
	var dst interface{}
 | 
			
		||||
	err := dec.Decode(&dst)
 | 
			
		||||
	return dst, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										665
									
								
								vendor/b612.me/notify/server.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										665
									
								
								vendor/b612.me/notify/server.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,665 @@
 | 
			
		||||
package notify
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/stario"
 | 
			
		||||
	"b612.me/starnet"
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"net"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ServerCommon struct {
 | 
			
		||||
	msgID                      uint64
 | 
			
		||||
	alive                      atomic.Value
 | 
			
		||||
	status                     Status
 | 
			
		||||
	listener                   net.Listener
 | 
			
		||||
	udpListener                *net.UDPConn
 | 
			
		||||
	queue                      *starnet.StarQueue
 | 
			
		||||
	stopFn                     context.CancelFunc
 | 
			
		||||
	stopCtx                    context.Context
 | 
			
		||||
	maxReadTimeout             time.Duration
 | 
			
		||||
	maxWriteTimeout            time.Duration
 | 
			
		||||
	parallelNum                int
 | 
			
		||||
	wg                         stario.WaitGroup
 | 
			
		||||
	clientPool                 map[string]*ClientConn
 | 
			
		||||
	mu                         sync.RWMutex
 | 
			
		||||
	handshakeRsaKey            []byte
 | 
			
		||||
	SecretKey                  []byte
 | 
			
		||||
	defaultMsgEn               func([]byte, []byte) []byte
 | 
			
		||||
	defaultMsgDe               func([]byte, []byte) []byte
 | 
			
		||||
	linkFns                    map[string]func(message *Message)
 | 
			
		||||
	defaultFns                 func(message *Message)
 | 
			
		||||
	noFinSyncMsgPool           sync.Map
 | 
			
		||||
	noFinSyncMsgMaxKeepSeconds int64
 | 
			
		||||
	maxHeartbeatLostSeconds    int64
 | 
			
		||||
	sequenceDe                 func([]byte) (interface{}, error)
 | 
			
		||||
	sequenceEn                 func(interface{}) ([]byte, error)
 | 
			
		||||
	showError                  bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewServer() Server {
 | 
			
		||||
	var server ServerCommon
 | 
			
		||||
	server.wg = stario.NewWaitGroup(0)
 | 
			
		||||
	server.parallelNum = 0
 | 
			
		||||
	server.noFinSyncMsgMaxKeepSeconds = 0
 | 
			
		||||
	server.maxHeartbeatLostSeconds = 300
 | 
			
		||||
	server.stopCtx, server.stopFn = context.WithCancel(context.Background())
 | 
			
		||||
	server.SecretKey = defaultAesKey
 | 
			
		||||
	server.handshakeRsaKey = defaultRsaKey
 | 
			
		||||
	server.clientPool = make(map[string]*ClientConn)
 | 
			
		||||
	server.defaultMsgEn = defaultMsgEn
 | 
			
		||||
	server.defaultMsgDe = defaultMsgDe
 | 
			
		||||
	server.sequenceEn = encode
 | 
			
		||||
	server.sequenceDe = Decode
 | 
			
		||||
	server.alive.Store(false)
 | 
			
		||||
	server.linkFns = make(map[string]func(*Message))
 | 
			
		||||
	server.defaultFns = func(message *Message) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	return &server
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) ShowError(std bool) {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	s.showError = std
 | 
			
		||||
	s.mu.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) Stop() error {
 | 
			
		||||
	if !s.alive.Load().(bool) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	s.alive.Store(false)
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	s.status = Status{
 | 
			
		||||
		Alive:  false,
 | 
			
		||||
		Reason: "recv stop signal from user",
 | 
			
		||||
		Err:    nil,
 | 
			
		||||
	}
 | 
			
		||||
	s.mu.Unlock()
 | 
			
		||||
	s.stopFn()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) Listen(network string, addr string) error {
 | 
			
		||||
	if s.alive.Load().(bool) {
 | 
			
		||||
		return errors.New("server already run")
 | 
			
		||||
	}
 | 
			
		||||
	s.stopCtx, s.stopFn = context.WithCancel(context.Background())
 | 
			
		||||
	s.queue = starnet.NewQueueCtx(s.stopCtx, 128)
 | 
			
		||||
	if strings.Contains(strings.ToLower(network), "udp") {
 | 
			
		||||
		return s.ListenUDP(network, addr)
 | 
			
		||||
	}
 | 
			
		||||
	return s.ListenTU(network, addr)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) ListenTU(network string, addr string) error {
 | 
			
		||||
	listener, err := net.Listen(network, addr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	s.alive.Store(true)
 | 
			
		||||
	s.status.Alive = true
 | 
			
		||||
	s.listener = listener
 | 
			
		||||
	go s.accept()
 | 
			
		||||
	go s.monitorPool()
 | 
			
		||||
	go s.loadMessage()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) monitorPool() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-s.stopCtx.Done():
 | 
			
		||||
			s.noFinSyncMsgPool.Range(func(k, v interface{}) bool {
 | 
			
		||||
				data := v.(WaitMsg)
 | 
			
		||||
				close(data.Reply)
 | 
			
		||||
				s.noFinSyncMsgPool.Delete(k)
 | 
			
		||||
				return true
 | 
			
		||||
			})
 | 
			
		||||
			return
 | 
			
		||||
		case <-time.After(time.Second * 30):
 | 
			
		||||
		}
 | 
			
		||||
		now := time.Now()
 | 
			
		||||
		if s.noFinSyncMsgMaxKeepSeconds > 0 {
 | 
			
		||||
			s.noFinSyncMsgPool.Range(func(k, v interface{}) bool {
 | 
			
		||||
				data := v.(WaitMsg)
 | 
			
		||||
				if data.Time.Add(time.Duration(s.noFinSyncMsgMaxKeepSeconds) * time.Second).Before(now) {
 | 
			
		||||
					close(data.Reply)
 | 
			
		||||
					s.noFinSyncMsgPool.Delete(k)
 | 
			
		||||
				}
 | 
			
		||||
				return true
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		if s.maxHeartbeatLostSeconds != 0 {
 | 
			
		||||
			for _, v := range s.clientPool {
 | 
			
		||||
				if now.Unix()-v.lastHeartBeat > s.maxHeartbeatLostSeconds {
 | 
			
		||||
					v.stopFn()
 | 
			
		||||
					s.removeClient(v)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SetDefaultCommEncode(fn func([]byte, []byte) []byte) {
 | 
			
		||||
	s.defaultMsgEn = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SetDefaultCommDecode(fn func([]byte, []byte) []byte) {
 | 
			
		||||
	s.defaultMsgDe = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SetDefaultLink(fn func(message *Message)) {
 | 
			
		||||
	s.defaultFns = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SetLink(key string, fn func(*Message)) {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	defer s.mu.Unlock()
 | 
			
		||||
	s.linkFns[key] = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) pushMessage(data []byte, source string) {
 | 
			
		||||
	s.queue.ParseMessage(data, source)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) removeClient(client *ClientConn) {
 | 
			
		||||
	s.mu.Lock()
 | 
			
		||||
	defer s.mu.Unlock()
 | 
			
		||||
	delete(s.clientPool, client.ClientID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) accept() {
 | 
			
		||||
	if s.udpListener != nil {
 | 
			
		||||
		s.acceptUDP()
 | 
			
		||||
	}
 | 
			
		||||
	s.acceptTU()
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) acceptTU() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-s.stopCtx.Done():
 | 
			
		||||
			return
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		conn, err := s.listener.Accept()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if s.showError {
 | 
			
		||||
				fmt.Println("error accept:", err)
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		var id string
 | 
			
		||||
		for {
 | 
			
		||||
			id = fmt.Sprintf("%s%d%d", conn.RemoteAddr().String(), time.Now().UnixNano(), rand.Int63())
 | 
			
		||||
			s.mu.RLock()
 | 
			
		||||
			if _, ok := s.clientPool[id]; ok {
 | 
			
		||||
				s.mu.RUnlock()
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			s.mu.RUnlock()
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		client := ClientConn{
 | 
			
		||||
			ClientID:        id,
 | 
			
		||||
			ClientAddr:      conn.RemoteAddr(),
 | 
			
		||||
			tuConn:          conn,
 | 
			
		||||
			server:          s,
 | 
			
		||||
			maxReadTimeout:  s.maxReadTimeout,
 | 
			
		||||
			maxWriteTimeout: s.maxWriteTimeout,
 | 
			
		||||
			SecretKey:       s.SecretKey,
 | 
			
		||||
			handshakeRsaKey: s.handshakeRsaKey,
 | 
			
		||||
			msgEn:           s.defaultMsgEn,
 | 
			
		||||
			msgDe:           s.defaultMsgDe,
 | 
			
		||||
			lastHeartBeat:   time.Now().Unix(),
 | 
			
		||||
		}
 | 
			
		||||
		client.alive.Store(true)
 | 
			
		||||
		client.status = Status{
 | 
			
		||||
			Alive:  true,
 | 
			
		||||
			Reason: "",
 | 
			
		||||
			Err:    nil,
 | 
			
		||||
		}
 | 
			
		||||
		client.stopCtx, client.stopFn = context.WithCancel(context.Background())
 | 
			
		||||
		s.mu.Lock()
 | 
			
		||||
		s.clientPool[id] = &client
 | 
			
		||||
		s.mu.Unlock()
 | 
			
		||||
		go client.readTUMessage()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) loadMessage() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-s.stopCtx.Done():
 | 
			
		||||
			var wg sync.WaitGroup
 | 
			
		||||
			s.mu.RLock()
 | 
			
		||||
			for _, v := range s.clientPool {
 | 
			
		||||
				wg.Add(1)
 | 
			
		||||
				go func() {
 | 
			
		||||
					defer wg.Done()
 | 
			
		||||
					v.sayGoodByeForTU()
 | 
			
		||||
					v.alive.Store(false)
 | 
			
		||||
					v.status = Status{
 | 
			
		||||
						Alive:  false,
 | 
			
		||||
						Reason: "recv stop signal from server",
 | 
			
		||||
						Err:    nil,
 | 
			
		||||
					}
 | 
			
		||||
					v.stopFn()
 | 
			
		||||
					s.removeClient(v)
 | 
			
		||||
				}()
 | 
			
		||||
			}
 | 
			
		||||
			s.mu.RUnlock()
 | 
			
		||||
			select {
 | 
			
		||||
			case <-time.After(time.Second * 8):
 | 
			
		||||
			case <-stario.WaitUntilFinished(func() error {
 | 
			
		||||
				wg.Wait()
 | 
			
		||||
				return nil
 | 
			
		||||
			}):
 | 
			
		||||
			}
 | 
			
		||||
			if s.listener != nil {
 | 
			
		||||
				s.listener.Close()
 | 
			
		||||
			}
 | 
			
		||||
			s.wg.Wait()
 | 
			
		||||
			return
 | 
			
		||||
		case data, ok := <-s.queue.RestoreChan():
 | 
			
		||||
			if !ok {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			s.wg.Add(1)
 | 
			
		||||
			go func(data starnet.MsgQueue) {
 | 
			
		||||
				s.mu.RLock()
 | 
			
		||||
				cc, ok := s.clientPool[data.Conn.(string)]
 | 
			
		||||
				s.mu.RUnlock()
 | 
			
		||||
				if !ok {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				//fmt.Println("received:", float64(time.Now().UnixNano()-nowd)/1000000)
 | 
			
		||||
				msg, err := s.sequenceDe(cc.msgDe(cc.SecretKey, data.Msg))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					if s.showError {
 | 
			
		||||
						fmt.Println("server decode data error", err)
 | 
			
		||||
					}
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				//fmt.Println("decoded:", float64(time.Now().UnixNano()-nowd)/1000000)
 | 
			
		||||
				message := Message{
 | 
			
		||||
					NetType:     NET_SERVER,
 | 
			
		||||
					ClientConn:  cc,
 | 
			
		||||
					TransferMsg: msg.(TransferMsg),
 | 
			
		||||
				}
 | 
			
		||||
				message.Time = time.Now()
 | 
			
		||||
 | 
			
		||||
				//fmt.Println("dispatch:", float64(time.Now().UnixNano()-nowd)/1000000)
 | 
			
		||||
				s.dispatchMsg(message)
 | 
			
		||||
			}(data)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) sysMsg(message Message) {
 | 
			
		||||
	switch message.Key {
 | 
			
		||||
	case "bye":
 | 
			
		||||
		//fmt.Println("recv stop signal from client", message.ClientConn.ClientID)
 | 
			
		||||
		if message.TransferMsg.Type == MSG_SYS_WAIT {
 | 
			
		||||
			message.Reply(nil)
 | 
			
		||||
		}
 | 
			
		||||
		message.ClientConn.alive.Store(false)
 | 
			
		||||
		message.ClientConn.status = Status{
 | 
			
		||||
			Alive:  false,
 | 
			
		||||
			Reason: "recv stop signal from client",
 | 
			
		||||
			Err:    nil,
 | 
			
		||||
		}
 | 
			
		||||
		message.ClientConn.stopFn()
 | 
			
		||||
	case "heartbeat":
 | 
			
		||||
		message.ClientConn.lastHeartBeat = time.Now().Unix()
 | 
			
		||||
		message.Reply(nil)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) dispatchMsg(message Message) {
 | 
			
		||||
	defer s.wg.Done()
 | 
			
		||||
	switch message.TransferMsg.Type {
 | 
			
		||||
	case MSG_SYS_WAIT:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case MSG_SYS:
 | 
			
		||||
		s.sysMsg(message)
 | 
			
		||||
		return
 | 
			
		||||
	case MSG_KEY_CHANGE:
 | 
			
		||||
		message.ClientConn.rsaDecode(message)
 | 
			
		||||
		return
 | 
			
		||||
	case MSG_SYS_REPLY:
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case MSG_SYNC_REPLY:
 | 
			
		||||
		data, ok := s.noFinSyncMsgPool.Load(message.TransferMsg.ID)
 | 
			
		||||
		if ok {
 | 
			
		||||
			wait := data.(WaitMsg)
 | 
			
		||||
			wait.Reply <- message
 | 
			
		||||
			s.noFinSyncMsgPool.Delete(message.TransferMsg.ID)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		//just throw
 | 
			
		||||
		return
 | 
			
		||||
		//fallthrough
 | 
			
		||||
	default:
 | 
			
		||||
	}
 | 
			
		||||
	callFn := func(fn func(*Message)) {
 | 
			
		||||
		fn(&message)
 | 
			
		||||
	}
 | 
			
		||||
	fn, ok := s.linkFns[message.TransferMsg.Key]
 | 
			
		||||
	if ok {
 | 
			
		||||
		callFn(fn)
 | 
			
		||||
	}
 | 
			
		||||
	if s.defaultFns != nil {
 | 
			
		||||
		callFn(s.defaultFns)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) send(c *ClientConn, msg TransferMsg) (WaitMsg, error) {
 | 
			
		||||
	if s.udpListener != nil {
 | 
			
		||||
		return s.sendUDP(c, msg)
 | 
			
		||||
	}
 | 
			
		||||
	return s.sendTU(c, msg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) sendTU(c *ClientConn, msg TransferMsg) (WaitMsg, error) {
 | 
			
		||||
	var wait WaitMsg
 | 
			
		||||
	if msg.Type != MSG_SYNC_REPLY && msg.Type != MSG_KEY_CHANGE && msg.Type != MSG_SYS_REPLY || msg.ID == 0 {
 | 
			
		||||
		msg.ID = atomic.AddUint64(&s.msgID, 1)
 | 
			
		||||
	}
 | 
			
		||||
	data, err := s.sequenceEn(msg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return WaitMsg{}, err
 | 
			
		||||
	}
 | 
			
		||||
	data = c.msgEn(c.SecretKey, data)
 | 
			
		||||
	data = s.queue.BuildMessage(data)
 | 
			
		||||
	if c.maxWriteTimeout.Seconds() != 0 {
 | 
			
		||||
		c.tuConn.SetWriteDeadline(time.Now().Add(c.maxWriteTimeout))
 | 
			
		||||
	}
 | 
			
		||||
	_, err = c.tuConn.Write(data)
 | 
			
		||||
	//fmt.Println("resend:", float64(time.Now().UnixNano()-nowd)/1000000)
 | 
			
		||||
	if err == nil && (msg.Type == MSG_SYNC_ASK || msg.Type == MSG_SYS_WAIT) {
 | 
			
		||||
		wait.Time = time.Now()
 | 
			
		||||
		wait.TransferMsg = msg
 | 
			
		||||
		wait.Reply = make(chan Message, 1)
 | 
			
		||||
		s.noFinSyncMsgPool.Store(msg.ID, wait)
 | 
			
		||||
	}
 | 
			
		||||
	return wait, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) Send(c *ClientConn, key string, value MsgVal) error {
 | 
			
		||||
	_, err := s.send(c, TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: value,
 | 
			
		||||
		Type:  MSG_ASYNC,
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) sendWait(c *ClientConn, msg TransferMsg, timeout time.Duration) (Message, error) {
 | 
			
		||||
	data, err := s.send(c, msg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Message{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if timeout.Seconds() == 0 {
 | 
			
		||||
		msg, ok := <-data.Reply
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return msg, os.ErrInvalid
 | 
			
		||||
		}
 | 
			
		||||
		return msg, nil
 | 
			
		||||
	}
 | 
			
		||||
	select {
 | 
			
		||||
	case <-time.After(timeout):
 | 
			
		||||
		close(data.Reply)
 | 
			
		||||
		s.noFinSyncMsgPool.Delete(data.TransferMsg.ID)
 | 
			
		||||
		return Message{}, os.ErrDeadlineExceeded
 | 
			
		||||
	case <-s.stopCtx.Done():
 | 
			
		||||
		return Message{}, errors.New("Service shutdown")
 | 
			
		||||
	case msg, ok := <-data.Reply:
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return msg, os.ErrInvalid
 | 
			
		||||
		}
 | 
			
		||||
		return msg, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SendCtx(ctx context.Context, c *ClientConn, key string, value MsgVal) (Message, error) {
 | 
			
		||||
	return s.sendCtx(c, TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: value,
 | 
			
		||||
		Type:  MSG_SYNC_ASK,
 | 
			
		||||
	}, ctx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) sendCtx(c *ClientConn, msg TransferMsg, ctx context.Context) (Message, error) {
 | 
			
		||||
	data, err := s.send(c, msg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Message{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if ctx == nil {
 | 
			
		||||
		ctx = context.Background()
 | 
			
		||||
	}
 | 
			
		||||
	select {
 | 
			
		||||
	case <-ctx.Done():
 | 
			
		||||
		close(data.Reply)
 | 
			
		||||
		s.noFinSyncMsgPool.Delete(data.TransferMsg.ID)
 | 
			
		||||
		return Message{}, os.ErrClosed
 | 
			
		||||
	case <-s.stopCtx.Done():
 | 
			
		||||
		return Message{}, errors.New("Service shutdown")
 | 
			
		||||
	case msg, ok := <-data.Reply:
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return msg, os.ErrInvalid
 | 
			
		||||
		}
 | 
			
		||||
		return msg, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) SendWait(c *ClientConn, key string, value MsgVal, timeout time.Duration) (Message, error) {
 | 
			
		||||
	return s.sendWait(c, TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: value,
 | 
			
		||||
		Type:  MSG_SYNC_ASK,
 | 
			
		||||
	}, timeout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SendWaitObj(c *ClientConn, key string, value interface{}, timeout time.Duration) (Message, error) {
 | 
			
		||||
	data, err := s.sequenceEn(value)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Message{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return s.SendWait(c, key, data, timeout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SendObjCtx(ctx context.Context, c *ClientConn, key string, val interface{}) (Message, error) {
 | 
			
		||||
	data, err := s.sequenceEn(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Message{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return s.sendCtx(c, TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: data,
 | 
			
		||||
		Type:  MSG_SYNC_ASK,
 | 
			
		||||
	}, ctx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SendObj(c *ClientConn, key string, val interface{}) error {
 | 
			
		||||
	data, err := encode(val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, err = s.send(c, TransferMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: data,
 | 
			
		||||
		Type:  MSG_ASYNC,
 | 
			
		||||
	})
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) Reply(m Message, value MsgVal) error {
 | 
			
		||||
	return m.Reply(value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//for udp below
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) ListenUDP(network string, addr string) error {
 | 
			
		||||
	udpAddr, err := net.ResolveUDPAddr(network, addr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	listener, err := net.ListenUDP(network, udpAddr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	s.alive.Store(true)
 | 
			
		||||
	s.status.Alive = true
 | 
			
		||||
	s.udpListener = listener
 | 
			
		||||
	go s.accept()
 | 
			
		||||
	go s.monitorPool()
 | 
			
		||||
	go s.loadMessage()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) acceptUDP() {
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-s.stopCtx.Done():
 | 
			
		||||
			return
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		if s.maxReadTimeout.Seconds() > 0 {
 | 
			
		||||
			s.udpListener.SetReadDeadline(time.Now().Add(s.maxReadTimeout))
 | 
			
		||||
		}
 | 
			
		||||
		data := make([]byte, 4096)
 | 
			
		||||
		num, addr, err := s.udpListener.ReadFromUDP(data)
 | 
			
		||||
		id := addr.String()
 | 
			
		||||
		//fmt.Println("s recv udp:", float64(time.Now().UnixNano()-nowd)/1000000)
 | 
			
		||||
		s.mu.RLock()
 | 
			
		||||
		if _, ok := s.clientPool[id]; !ok {
 | 
			
		||||
			s.mu.RUnlock()
 | 
			
		||||
			client := ClientConn{
 | 
			
		||||
				ClientID:        id,
 | 
			
		||||
				ClientAddr:      addr,
 | 
			
		||||
				server:          s,
 | 
			
		||||
				maxReadTimeout:  s.maxReadTimeout,
 | 
			
		||||
				maxWriteTimeout: s.maxWriteTimeout,
 | 
			
		||||
				SecretKey:       s.SecretKey,
 | 
			
		||||
				handshakeRsaKey: s.handshakeRsaKey,
 | 
			
		||||
				msgEn:           s.defaultMsgEn,
 | 
			
		||||
				msgDe:           s.defaultMsgDe,
 | 
			
		||||
				lastHeartBeat:   time.Now().Unix(),
 | 
			
		||||
			}
 | 
			
		||||
			client.stopCtx, client.stopFn = context.WithCancel(context.Background())
 | 
			
		||||
			s.mu.Lock()
 | 
			
		||||
			s.clientPool[id] = &client
 | 
			
		||||
			s.mu.Unlock()
 | 
			
		||||
		} else {
 | 
			
		||||
			s.mu.RUnlock()
 | 
			
		||||
		}
 | 
			
		||||
		if err == os.ErrDeadlineExceeded {
 | 
			
		||||
			if num != 0 {
 | 
			
		||||
				s.pushMessage(data[:num], id)
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		s.pushMessage(data[:num], id)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) sendUDP(c *ClientConn, msg TransferMsg) (WaitMsg, error) {
 | 
			
		||||
	var wait WaitMsg
 | 
			
		||||
	if msg.Type != MSG_SYNC_REPLY && msg.Type != MSG_KEY_CHANGE && msg.Type != MSG_SYS_REPLY || msg.ID == 0 {
 | 
			
		||||
		msg.ID = uint64(time.Now().UnixNano()) + rand.Uint64() + rand.Uint64()
 | 
			
		||||
	}
 | 
			
		||||
	data, err := s.sequenceEn(msg)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return WaitMsg{}, err
 | 
			
		||||
	}
 | 
			
		||||
	data = c.msgEn(c.SecretKey, data)
 | 
			
		||||
	data = s.queue.BuildMessage(data)
 | 
			
		||||
	if c.maxWriteTimeout.Seconds() != 0 {
 | 
			
		||||
		s.udpListener.SetWriteDeadline(time.Now().Add(c.maxWriteTimeout))
 | 
			
		||||
	}
 | 
			
		||||
	_, err = s.udpListener.WriteTo(data, c.ClientAddr)
 | 
			
		||||
	if err == nil && (msg.Type == MSG_SYNC_ASK || msg.Type == MSG_SYS_WAIT) {
 | 
			
		||||
		wait.Time = time.Now()
 | 
			
		||||
		wait.TransferMsg = msg
 | 
			
		||||
		wait.Reply = make(chan Message, 1)
 | 
			
		||||
		s.noFinSyncMsgPool.Store(msg.ID, wait)
 | 
			
		||||
	}
 | 
			
		||||
	return wait, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) StopMonitorChan() <-chan struct{} {
 | 
			
		||||
	return s.stopCtx.Done()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) Status() Status {
 | 
			
		||||
	return s.status
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) GetSecretKey() []byte {
 | 
			
		||||
	return s.SecretKey
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) SetSecretKey(key []byte) {
 | 
			
		||||
	s.SecretKey = key
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) RsaPrivKey() []byte {
 | 
			
		||||
	return s.handshakeRsaKey
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) SetRsaPrivKey(key []byte) {
 | 
			
		||||
	s.handshakeRsaKey = key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) GetClient(id string) *ClientConn {
 | 
			
		||||
	s.mu.RLock()
 | 
			
		||||
	defer s.mu.RUnlock()
 | 
			
		||||
	c, ok := s.clientPool[id]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) GetClientLists() []*ClientConn {
 | 
			
		||||
	s.mu.RLock()
 | 
			
		||||
	defer s.mu.RUnlock()
 | 
			
		||||
	var list []*ClientConn = make([]*ClientConn, 0, len(s.clientPool))
 | 
			
		||||
	for _, v := range s.clientPool {
 | 
			
		||||
		list = append(list, v)
 | 
			
		||||
	}
 | 
			
		||||
	return list
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) GetClientAddrs() []net.Addr {
 | 
			
		||||
	s.mu.RLock()
 | 
			
		||||
	defer s.mu.RUnlock()
 | 
			
		||||
	var list = make([]net.Addr, 0, len(s.clientPool))
 | 
			
		||||
	for _, v := range s.clientPool {
 | 
			
		||||
		list = append(list, v.ClientAddr)
 | 
			
		||||
	}
 | 
			
		||||
	return list
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) GetSequenceEn() func(interface{}) ([]byte, error) {
 | 
			
		||||
	return s.sequenceEn
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) SetSequenceEn(fn func(interface{}) ([]byte, error)) {
 | 
			
		||||
	s.sequenceEn = fn
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) GetSequenceDe() func([]byte) (interface{}, error) {
 | 
			
		||||
	return s.sequenceDe
 | 
			
		||||
}
 | 
			
		||||
func (s *ServerCommon) SetSequenceDe(fn func([]byte) (interface{}, error)) {
 | 
			
		||||
	s.sequenceDe = fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) HeartbeatTimeoutSec() int64 {
 | 
			
		||||
	return s.maxHeartbeatLostSeconds
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *ServerCommon) SetHeartbeatTimeoutSec(sec int64) {
 | 
			
		||||
	s.maxHeartbeatLostSeconds = sec
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								vendor/b612.me/notify/servertype.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								vendor/b612.me/notify/servertype.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
package notify
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Server interface {
 | 
			
		||||
	SetDefaultCommEncode(func([]byte, []byte) []byte)
 | 
			
		||||
	SetDefaultCommDecode(func([]byte, []byte) []byte)
 | 
			
		||||
	SetDefaultLink(func(message *Message))
 | 
			
		||||
	SetLink(string, func(*Message))
 | 
			
		||||
	send(c *ClientConn, msg TransferMsg) (WaitMsg, error)
 | 
			
		||||
	sendWait(c *ClientConn, msg TransferMsg, timeout time.Duration) (Message, error)
 | 
			
		||||
	SendObjCtx(ctx context.Context, c *ClientConn, key string, val interface{}) (Message, error)
 | 
			
		||||
	SendObj(c *ClientConn, key string, val interface{}) error
 | 
			
		||||
	Send(c *ClientConn, key string, value MsgVal) error
 | 
			
		||||
	SendWait(c *ClientConn, key string, value MsgVal, timeout time.Duration) (Message, error)
 | 
			
		||||
	SendWaitObj(c *ClientConn, key string, value interface{}, timeout time.Duration) (Message, error)
 | 
			
		||||
	SendCtx(ctx context.Context, c *ClientConn, key string, value MsgVal) (Message, error)
 | 
			
		||||
	Reply(m Message, value MsgVal) error
 | 
			
		||||
	pushMessage([]byte, string)
 | 
			
		||||
	removeClient(client *ClientConn)
 | 
			
		||||
	Listen(network string, addr string) error
 | 
			
		||||
	Stop() error
 | 
			
		||||
	StopMonitorChan() <-chan struct{}
 | 
			
		||||
	Status() Status
 | 
			
		||||
 | 
			
		||||
	GetSecretKey() []byte
 | 
			
		||||
	SetSecretKey(key []byte)
 | 
			
		||||
	RsaPrivKey() []byte
 | 
			
		||||
	SetRsaPrivKey([]byte)
 | 
			
		||||
 | 
			
		||||
	GetClient(id string) *ClientConn
 | 
			
		||||
	GetClientLists() []*ClientConn
 | 
			
		||||
	GetClientAddrs() []net.Addr
 | 
			
		||||
 | 
			
		||||
	GetSequenceEn() func(interface{}) ([]byte, error)
 | 
			
		||||
	SetSequenceEn(func(interface{}) ([]byte, error))
 | 
			
		||||
	GetSequenceDe() func([]byte) (interface{}, error)
 | 
			
		||||
	SetSequenceDe(func([]byte) (interface{}, error))
 | 
			
		||||
	ShowError(bool)
 | 
			
		||||
 | 
			
		||||
	HeartbeatTimeoutSec() int64
 | 
			
		||||
	SetHeartbeatTimeoutSec(int64)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										103
									
								
								vendor/b612.me/starcrypto/crc32a.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								vendor/b612.me/starcrypto/crc32a.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,103 @@
 | 
			
		||||
package starcrypto
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"encoding/hex"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CheckCRC32A calculates CRC32A (ITU I.363.5 algorithm, popularized by BZIP2) checksum.
 | 
			
		||||
// This function will produce the same results as following PHP code:
 | 
			
		||||
//  hexdec(hash('crc32', $data))
 | 
			
		||||
func CheckCRC32A(data []byte) uint32 {
 | 
			
		||||
	b := digest(data)
 | 
			
		||||
 | 
			
		||||
	return binary.BigEndian.Uint32(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Crc32A(data []byte) []byte {
 | 
			
		||||
	return digest(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Crc32AStr is a convenience function that outputs CRC32A (ITU I.363.5 algorithm, popularized by BZIP2) checksum as a hex string.
 | 
			
		||||
// This function will produce the same results as following PHP code:
 | 
			
		||||
//  hash('crc32', $data)
 | 
			
		||||
func Crc32AStr(data []byte) string {
 | 
			
		||||
	b := digest(data)
 | 
			
		||||
 | 
			
		||||
	return hex.EncodeToString(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// digest performs checksum calculation for each byte of provided data and returns digest in form of byte array.
 | 
			
		||||
func digest(data []byte) []byte {
 | 
			
		||||
	var crc uint32
 | 
			
		||||
	var digest = make([]byte, 4)
 | 
			
		||||
 | 
			
		||||
	crc = ^crc
 | 
			
		||||
	for i := 0; i < len(data); i++ {
 | 
			
		||||
		crc = (crc << 8) ^ table[(crc>>24)^(uint32(data[i])&0xff)]
 | 
			
		||||
	}
 | 
			
		||||
	crc = ^crc
 | 
			
		||||
 | 
			
		||||
	digest[3] = byte((crc >> 24) & 0xff)
 | 
			
		||||
	digest[2] = byte((crc >> 16) & 0xff)
 | 
			
		||||
	digest[1] = byte((crc >> 8) & 0xff)
 | 
			
		||||
	digest[0] = byte(crc & 0xff)
 | 
			
		||||
 | 
			
		||||
	return digest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// table is the pre-generated 0x04C11DB7 polynominal used for CRC32A.
 | 
			
		||||
var table = [256]uint32{
 | 
			
		||||
	0x0,
 | 
			
		||||
	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
 | 
			
		||||
	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
 | 
			
		||||
	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
 | 
			
		||||
	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
 | 
			
		||||
	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
 | 
			
		||||
	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
 | 
			
		||||
	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
 | 
			
		||||
	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
 | 
			
		||||
	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
 | 
			
		||||
	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
 | 
			
		||||
	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
 | 
			
		||||
	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
 | 
			
		||||
	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
 | 
			
		||||
	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
 | 
			
		||||
	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
 | 
			
		||||
	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
 | 
			
		||||
	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
 | 
			
		||||
	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
 | 
			
		||||
	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
 | 
			
		||||
	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
 | 
			
		||||
	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
 | 
			
		||||
	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
 | 
			
		||||
	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
 | 
			
		||||
	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
 | 
			
		||||
	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
 | 
			
		||||
	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
 | 
			
		||||
	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
 | 
			
		||||
	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
 | 
			
		||||
	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
 | 
			
		||||
	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
 | 
			
		||||
	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
 | 
			
		||||
	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
 | 
			
		||||
	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
 | 
			
		||||
	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
 | 
			
		||||
	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
 | 
			
		||||
	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
 | 
			
		||||
	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
 | 
			
		||||
	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
 | 
			
		||||
	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
 | 
			
		||||
	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
 | 
			
		||||
	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
 | 
			
		||||
	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
 | 
			
		||||
	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
 | 
			
		||||
	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
 | 
			
		||||
	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
 | 
			
		||||
	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
 | 
			
		||||
	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
 | 
			
		||||
	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
 | 
			
		||||
	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
 | 
			
		||||
	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
 | 
			
		||||
	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1250
									
								
								vendor/b612.me/starcrypto/crypto.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1250
									
								
								vendor/b612.me/starcrypto/crypto.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										149
									
								
								vendor/b612.me/stario/circle.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								vendor/b612.me/stario/circle.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,149 @@
 | 
			
		||||
package stario
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type StarBuffer struct {
 | 
			
		||||
	io.Reader
 | 
			
		||||
	io.Writer
 | 
			
		||||
	io.Closer
 | 
			
		||||
	datas   []byte
 | 
			
		||||
	pStart  uint64
 | 
			
		||||
	pEnd    uint64
 | 
			
		||||
	cap     uint64
 | 
			
		||||
	isClose atomic.Value
 | 
			
		||||
	isEnd   atomic.Value
 | 
			
		||||
	rmu     sync.Mutex
 | 
			
		||||
	wmu     sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewStarBuffer(cap uint64) *StarBuffer {
 | 
			
		||||
	rtnBuffer := new(StarBuffer)
 | 
			
		||||
	rtnBuffer.cap = cap
 | 
			
		||||
	rtnBuffer.datas = make([]byte, cap)
 | 
			
		||||
	rtnBuffer.isClose.Store(false)
 | 
			
		||||
	rtnBuffer.isEnd.Store(false)
 | 
			
		||||
	return rtnBuffer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarBuffer) Free() uint64 {
 | 
			
		||||
	return star.cap - star.Len()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarBuffer) Cap() uint64 {
 | 
			
		||||
	return star.cap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarBuffer) Len() uint64 {
 | 
			
		||||
	if star.pEnd >= star.pStart {
 | 
			
		||||
		return star.pEnd - star.pStart
 | 
			
		||||
	}
 | 
			
		||||
	return star.pEnd - star.pStart + star.cap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarBuffer) getByte() (byte, error) {
 | 
			
		||||
	if star.isClose.Load().(bool) || (star.Len() == 0 && star.isEnd.Load().(bool)) {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	if star.Len() == 0 {
 | 
			
		||||
		return 0, os.ErrNotExist
 | 
			
		||||
	}
 | 
			
		||||
	nowPtr := star.pStart
 | 
			
		||||
	nextPtr := star.pStart + 1
 | 
			
		||||
	if nextPtr >= star.cap {
 | 
			
		||||
		nextPtr = 0
 | 
			
		||||
	}
 | 
			
		||||
	data := star.datas[nowPtr]
 | 
			
		||||
	ok := atomic.CompareAndSwapUint64(&star.pStart, nowPtr, nextPtr)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return 0, os.ErrInvalid
 | 
			
		||||
	}
 | 
			
		||||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarBuffer) putByte(data byte) error {
 | 
			
		||||
	if star.isClose.Load().(bool) {
 | 
			
		||||
		return io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	nowPtr := star.pEnd
 | 
			
		||||
	kariEnd := nowPtr + 1
 | 
			
		||||
	if kariEnd == star.cap {
 | 
			
		||||
		kariEnd = 0
 | 
			
		||||
	}
 | 
			
		||||
	if kariEnd == atomic.LoadUint64(&star.pStart) {
 | 
			
		||||
		for {
 | 
			
		||||
			time.Sleep(time.Microsecond)
 | 
			
		||||
			runtime.Gosched()
 | 
			
		||||
			if kariEnd != atomic.LoadUint64(&star.pStart) {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	star.datas[nowPtr] = data
 | 
			
		||||
	if ok := atomic.CompareAndSwapUint64(&star.pEnd, nowPtr, kariEnd); !ok {
 | 
			
		||||
		return os.ErrInvalid
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarBuffer) Close() error {
 | 
			
		||||
	star.isClose.Store(true)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func (star *StarBuffer) Read(buf []byte) (int, error) {
 | 
			
		||||
	if star.isClose.Load().(bool) || (star.Len() == 0 && star.isEnd.Load().(bool)) {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	if buf == nil {
 | 
			
		||||
		return 0, errors.New("buffer is nil")
 | 
			
		||||
	}
 | 
			
		||||
	star.rmu.Lock()
 | 
			
		||||
	defer star.rmu.Unlock()
 | 
			
		||||
	var sum int = 0
 | 
			
		||||
	for i := 0; i < len(buf); i++ {
 | 
			
		||||
		data, err := star.getByte()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err == io.EOF {
 | 
			
		||||
				return sum, err
 | 
			
		||||
			}
 | 
			
		||||
			if err == os.ErrNotExist {
 | 
			
		||||
				i--
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			return sum, nil
 | 
			
		||||
		}
 | 
			
		||||
		buf[i] = data
 | 
			
		||||
		sum++
 | 
			
		||||
	}
 | 
			
		||||
	return sum, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarBuffer) Write(bts []byte) (int, error) {
 | 
			
		||||
	if bts == nil && !star.isEnd.Load().(bool) {
 | 
			
		||||
		star.isEnd.Store(true)
 | 
			
		||||
		return 0, nil
 | 
			
		||||
	}
 | 
			
		||||
	if bts == nil || star.isClose.Load().(bool) {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	star.wmu.Lock()
 | 
			
		||||
	defer star.wmu.Unlock()
 | 
			
		||||
	var sum = 0
 | 
			
		||||
	for i := 0; i < len(bts); i++ {
 | 
			
		||||
		err := star.putByte(bts[i])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Println("Write bts err:", err)
 | 
			
		||||
			return sum, err
 | 
			
		||||
		}
 | 
			
		||||
		sum++
 | 
			
		||||
	}
 | 
			
		||||
	return sum, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								vendor/b612.me/stario/fn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								vendor/b612.me/stario/fn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
package stario
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var ERR_TIMEOUT = errors.New("TIME OUT")
 | 
			
		||||
 | 
			
		||||
func WaitUntilTimeout(tm time.Duration, fn func(chan struct{}) error) error {
 | 
			
		||||
	var err error
 | 
			
		||||
	finished := make(chan struct{})
 | 
			
		||||
	imout := make(chan struct{})
 | 
			
		||||
	go func() {
 | 
			
		||||
		err = fn(imout)
 | 
			
		||||
		finished <- struct{}{}
 | 
			
		||||
	}()
 | 
			
		||||
	select {
 | 
			
		||||
	case <-finished:
 | 
			
		||||
		return err
 | 
			
		||||
	case <-time.After(tm):
 | 
			
		||||
		close(imout)
 | 
			
		||||
		return ERR_TIMEOUT
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WaitUntilFinished(fn func() error) <-chan error {
 | 
			
		||||
	finished := make(chan error)
 | 
			
		||||
	go func() {
 | 
			
		||||
		err := fn()
 | 
			
		||||
		finished <- err
 | 
			
		||||
	}()
 | 
			
		||||
	return finished
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WaitUntilTimeoutFinished(tm time.Duration, fn func(chan struct{}) error) <-chan error {
 | 
			
		||||
	var err error
 | 
			
		||||
	finished := make(chan struct{})
 | 
			
		||||
	result := make(chan error)
 | 
			
		||||
	imout := make(chan struct{})
 | 
			
		||||
	go func() {
 | 
			
		||||
		err = fn(imout)
 | 
			
		||||
		finished <- struct{}{}
 | 
			
		||||
	}()
 | 
			
		||||
	go func() {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-finished:
 | 
			
		||||
			result <- err
 | 
			
		||||
		case <-time.After(tm):
 | 
			
		||||
			close(imout)
 | 
			
		||||
			result <- ERR_TIMEOUT
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										411
									
								
								vendor/b612.me/stario/io.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										411
									
								
								vendor/b612.me/stario/io.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,411 @@
 | 
			
		||||
package stario
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bufio"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/ssh/terminal"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type InputMsg struct {
 | 
			
		||||
	msg             string
 | 
			
		||||
	err             error
 | 
			
		||||
	skipSliceSigErr bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Passwd(hint string, defaultVal string) InputMsg {
 | 
			
		||||
	return passwd(hint, defaultVal, "")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func PasswdWithMask(hint string, defaultVal string, mask string) InputMsg {
 | 
			
		||||
	return passwd(hint, defaultVal, mask)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MessageBoxRaw(hint string, defaultVal string) InputMsg {
 | 
			
		||||
	return messageBox(hint, defaultVal)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func messageBox(hint string, defaultVal string) InputMsg {
 | 
			
		||||
	var ioBuf []rune
 | 
			
		||||
	if hint != "" {
 | 
			
		||||
		fmt.Print(hint)
 | 
			
		||||
	}
 | 
			
		||||
	if strings.Index(hint, "\n") >= 0 {
 | 
			
		||||
		hint = strings.TrimSpace(hint[strings.LastIndex(hint, "\n"):])
 | 
			
		||||
	}
 | 
			
		||||
	fd := int(os.Stdin.Fd())
 | 
			
		||||
	state, err := terminal.MakeRaw(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return InputMsg{msg: "", err: err}
 | 
			
		||||
	}
 | 
			
		||||
	defer fmt.Println()
 | 
			
		||||
	defer terminal.Restore(fd, state)
 | 
			
		||||
	inputReader := bufio.NewReader(os.Stdin)
 | 
			
		||||
	for {
 | 
			
		||||
		b, _, err := inputReader.ReadRune()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return InputMsg{msg: "", err: err}
 | 
			
		||||
		}
 | 
			
		||||
		if b == 0x0d {
 | 
			
		||||
			strValue := strings.TrimSpace(string(ioBuf))
 | 
			
		||||
			if len(strValue) == 0 {
 | 
			
		||||
				strValue = defaultVal
 | 
			
		||||
			}
 | 
			
		||||
			return InputMsg{msg: strValue, err: err}
 | 
			
		||||
		}
 | 
			
		||||
		if b == 0x08 || b == 0x7F {
 | 
			
		||||
			if len(ioBuf) > 0 {
 | 
			
		||||
				ioBuf = ioBuf[:len(ioBuf)-1]
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Print("\r")
 | 
			
		||||
			for i := 0; i < len(ioBuf)+2+len(hint); i++ {
 | 
			
		||||
				fmt.Print(" ")
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			ioBuf = append(ioBuf, b)
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Print("\r")
 | 
			
		||||
		if hint != "" {
 | 
			
		||||
			fmt.Print(hint)
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Print(string(ioBuf))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func passwd(hint string, defaultVal string, mask string) InputMsg {
 | 
			
		||||
	var ioBuf []rune
 | 
			
		||||
	if hint != "" {
 | 
			
		||||
		fmt.Print(hint)
 | 
			
		||||
	}
 | 
			
		||||
	if strings.Index(hint, "\n") >= 0 {
 | 
			
		||||
		hint = strings.TrimSpace(hint[strings.LastIndex(hint, "\n"):])
 | 
			
		||||
	}
 | 
			
		||||
	fd := int(os.Stdin.Fd())
 | 
			
		||||
	state, err := terminal.MakeRaw(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return InputMsg{msg: "", err: err}
 | 
			
		||||
	}
 | 
			
		||||
	defer fmt.Println()
 | 
			
		||||
	defer terminal.Restore(fd, state)
 | 
			
		||||
	inputReader := bufio.NewReader(os.Stdin)
 | 
			
		||||
	for {
 | 
			
		||||
		b, _, err := inputReader.ReadRune()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return InputMsg{msg: "", err: err}
 | 
			
		||||
		}
 | 
			
		||||
		if b == 0x0d {
 | 
			
		||||
			strValue := strings.TrimSpace(string(ioBuf))
 | 
			
		||||
			if len(strValue) == 0 {
 | 
			
		||||
				strValue = defaultVal
 | 
			
		||||
			}
 | 
			
		||||
			return InputMsg{msg: strValue, err: err}
 | 
			
		||||
		}
 | 
			
		||||
		if b == 0x08 || b == 0x7F {
 | 
			
		||||
			if len(ioBuf) > 0 {
 | 
			
		||||
				ioBuf = ioBuf[:len(ioBuf)-1]
 | 
			
		||||
			}
 | 
			
		||||
			fmt.Print("\r")
 | 
			
		||||
			for i := 0; i < len(ioBuf)+2+len(hint); i++ {
 | 
			
		||||
				fmt.Print(" ")
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			ioBuf = append(ioBuf, b)
 | 
			
		||||
		}
 | 
			
		||||
		fmt.Print("\r")
 | 
			
		||||
		if hint != "" {
 | 
			
		||||
			fmt.Print(hint)
 | 
			
		||||
		}
 | 
			
		||||
		for i := 0; i < len(ioBuf); i++ {
 | 
			
		||||
			fmt.Print(mask)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MessageBox(hint string, defaultVal string) InputMsg {
 | 
			
		||||
	if hint != "" {
 | 
			
		||||
		fmt.Print(hint)
 | 
			
		||||
	}
 | 
			
		||||
	inputReader := bufio.NewReader(os.Stdin)
 | 
			
		||||
	str, err := inputReader.ReadString('\n')
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return InputMsg{msg: str, err: err}
 | 
			
		||||
	}
 | 
			
		||||
	str = strings.TrimSpace(str)
 | 
			
		||||
	if len(str) == 0 {
 | 
			
		||||
		str = defaultVal
 | 
			
		||||
	}
 | 
			
		||||
	return InputMsg{msg: str, err: err}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) IgnoreSliceParseError(i bool) InputMsg {
 | 
			
		||||
	im.skipSliceSigErr = i
 | 
			
		||||
	return im
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) String() (string, error) {
 | 
			
		||||
	if im.err != nil {
 | 
			
		||||
		return "", im.err
 | 
			
		||||
	}
 | 
			
		||||
	return im.msg, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustString() string {
 | 
			
		||||
	res, _ := im.String()
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) SliceString(sep string) ([]string, error) {
 | 
			
		||||
	if im.err != nil {
 | 
			
		||||
		return nil, im.err
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Split(im.msg, sep), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustSliceString(sep string) []string {
 | 
			
		||||
	res, _ := im.SliceString(sep)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) sliceFn(sep string, fn func(string) (interface{}, error)) ([]interface{}, error) {
 | 
			
		||||
	var res []interface{}
 | 
			
		||||
	data, err := im.SliceString(sep)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		code, err := fn(v)
 | 
			
		||||
		if err != nil && !im.skipSliceSigErr {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		} else if err == nil {
 | 
			
		||||
			res = append(res, code)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) Int() (int, error) {
 | 
			
		||||
	if im.err != nil {
 | 
			
		||||
		return 0, im.err
 | 
			
		||||
	}
 | 
			
		||||
	return strconv.Atoi(im.msg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) SliceInt(sep string) ([]int, error) {
 | 
			
		||||
	data, err := im.sliceFn(sep, func(v string) (interface{}, error) {
 | 
			
		||||
		return strconv.Atoi(v)
 | 
			
		||||
	})
 | 
			
		||||
	var res []int
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		res = append(res, v.(int))
 | 
			
		||||
	}
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustSliceInt(sep string) []int {
 | 
			
		||||
	res, _ := im.SliceInt(sep)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustInt() int {
 | 
			
		||||
	res, _ := im.Int()
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) Int64() (int64, error) {
 | 
			
		||||
	if im.err != nil {
 | 
			
		||||
		return 0, im.err
 | 
			
		||||
	}
 | 
			
		||||
	return strconv.ParseInt(im.msg, 10, 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustInt64() int64 {
 | 
			
		||||
	res, _ := im.Int64()
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) SliceInt64(sep string) ([]int64, error) {
 | 
			
		||||
	data, err := im.sliceFn(sep, func(v string) (interface{}, error) {
 | 
			
		||||
		return strconv.ParseInt(v, 10, 64)
 | 
			
		||||
	})
 | 
			
		||||
	var res []int64
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		res = append(res, v.(int64))
 | 
			
		||||
	}
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustSliceInt64(sep string) []int64 {
 | 
			
		||||
	res, _ := im.SliceInt64(sep)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) Uint64() (uint64, error) {
 | 
			
		||||
	if im.err != nil {
 | 
			
		||||
		return 0, im.err
 | 
			
		||||
	}
 | 
			
		||||
	return strconv.ParseUint(im.msg, 10, 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustUint64() uint64 {
 | 
			
		||||
	res, _ := im.Uint64()
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
func (im InputMsg) SliceUint64(sep string) ([]uint64, error) {
 | 
			
		||||
	data, err := im.sliceFn(sep, func(v string) (interface{}, error) {
 | 
			
		||||
		return strconv.ParseUint(v, 10, 64)
 | 
			
		||||
	})
 | 
			
		||||
	var res []uint64
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		res = append(res, v.(uint64))
 | 
			
		||||
	}
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustSliceUint64(sep string) []uint64 {
 | 
			
		||||
	res, _ := im.SliceUint64(sep)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) Bool() (bool, error) {
 | 
			
		||||
	if im.err != nil {
 | 
			
		||||
		return false, im.err
 | 
			
		||||
	}
 | 
			
		||||
	return strconv.ParseBool(im.msg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustBool() bool {
 | 
			
		||||
	res, _ := im.Bool()
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) SliceBool(sep string) ([]bool, error) {
 | 
			
		||||
	data, err := im.sliceFn(sep, func(v string) (interface{}, error) {
 | 
			
		||||
		return strconv.ParseBool(v)
 | 
			
		||||
	})
 | 
			
		||||
	var res []bool
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		res = append(res, v.(bool))
 | 
			
		||||
	}
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustSliceBool(sep string) []bool {
 | 
			
		||||
	res, _ := im.SliceBool(sep)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) Float64() (float64, error) {
 | 
			
		||||
	if im.err != nil {
 | 
			
		||||
		return 0, im.err
 | 
			
		||||
	}
 | 
			
		||||
	return strconv.ParseFloat(im.msg, 64)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustFloat64() float64 {
 | 
			
		||||
	res, _ := im.Float64()
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) SliceFloat64(sep string) ([]float64, error) {
 | 
			
		||||
	data, err := im.sliceFn(sep, func(v string) (interface{}, error) {
 | 
			
		||||
		return strconv.ParseFloat(v, 64)
 | 
			
		||||
	})
 | 
			
		||||
	var res []float64
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		res = append(res, v.(float64))
 | 
			
		||||
	}
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustSliceFloat64(sep string) []float64 {
 | 
			
		||||
	res, _ := im.SliceFloat64(sep)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) Float32() (float32, error) {
 | 
			
		||||
	if im.err != nil {
 | 
			
		||||
		return 0, im.err
 | 
			
		||||
	}
 | 
			
		||||
	res, err := strconv.ParseFloat(im.msg, 32)
 | 
			
		||||
	return float32(res), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustFloat32() float32 {
 | 
			
		||||
	res, _ := im.Float32()
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) SliceFloat32(sep string) ([]float32, error) {
 | 
			
		||||
	data, err := im.sliceFn(sep, func(v string) (interface{}, error) {
 | 
			
		||||
		return strconv.ParseFloat(v, 32)
 | 
			
		||||
	})
 | 
			
		||||
	var res []float32
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		res = append(res, v.(float32))
 | 
			
		||||
	}
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (im InputMsg) MustSliceFloat32(sep string) []float32 {
 | 
			
		||||
	res, _ := im.SliceFloat32(sep)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func YesNo(hint string, defaults bool) bool {
 | 
			
		||||
	for {
 | 
			
		||||
		res := strings.ToUpper(MessageBox(hint, "").MustString())
 | 
			
		||||
		if res == "" {
 | 
			
		||||
			return defaults
 | 
			
		||||
		}
 | 
			
		||||
		res = res[0:1]
 | 
			
		||||
		if res == "Y" {
 | 
			
		||||
			return true
 | 
			
		||||
		} else if res == "N" {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StopUntil(hint string, trigger string, repeat bool) error {
 | 
			
		||||
	pressLen := len([]rune(trigger))
 | 
			
		||||
	if trigger == "" {
 | 
			
		||||
		pressLen = 1
 | 
			
		||||
	}
 | 
			
		||||
	fd := int(os.Stdin.Fd())
 | 
			
		||||
	if hint != "" {
 | 
			
		||||
		fmt.Print(hint)
 | 
			
		||||
	}
 | 
			
		||||
	state, err := terminal.MakeRaw(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer terminal.Restore(fd, state)
 | 
			
		||||
	inputReader := bufio.NewReader(os.Stdin)
 | 
			
		||||
	//ioBuf := make([]byte, pressLen)
 | 
			
		||||
	i := 0
 | 
			
		||||
	for {
 | 
			
		||||
		b, _, err := inputReader.ReadRune()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if trigger == "" {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if b == []rune(trigger)[i] {
 | 
			
		||||
			i++
 | 
			
		||||
			if i == pressLen {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		i = 0
 | 
			
		||||
		if hint != "" && repeat {
 | 
			
		||||
			fmt.Print("\r\n")
 | 
			
		||||
			fmt.Print(hint)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								vendor/b612.me/stario/sync.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								vendor/b612.me/stario/sync.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
package stario
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type WaitGroup struct {
 | 
			
		||||
	wg       *sync.WaitGroup
 | 
			
		||||
	maxCount uint32
 | 
			
		||||
	allCount uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewWaitGroup(maxCount int) WaitGroup {
 | 
			
		||||
	return WaitGroup{wg: &sync.WaitGroup{}, maxCount: uint32(maxCount)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) Add(delta int) {
 | 
			
		||||
	var Udelta uint32
 | 
			
		||||
	if delta < 0 {
 | 
			
		||||
		Udelta = uint32(-delta - 1)
 | 
			
		||||
	} else {
 | 
			
		||||
		Udelta = uint32(delta)
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		allC := atomic.LoadUint32(&swg.allCount)
 | 
			
		||||
		if atomic.LoadUint32(&swg.maxCount) == 0 || atomic.LoadUint32(&swg.maxCount) >= allC+uint32(delta) {
 | 
			
		||||
			if delta < 0 {
 | 
			
		||||
				atomic.AddUint32(&swg.allCount, ^uint32(Udelta))
 | 
			
		||||
			} else {
 | 
			
		||||
				atomic.AddUint32(&swg.allCount, uint32(Udelta))
 | 
			
		||||
			}
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		time.Sleep(time.Microsecond)
 | 
			
		||||
	}
 | 
			
		||||
	swg.wg.Add(delta)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) Done() {
 | 
			
		||||
	swg.Add(-1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) Wait() {
 | 
			
		||||
	swg.wg.Wait()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) GetMaxWaitNum() int {
 | 
			
		||||
	return int(atomic.LoadUint32(&swg.maxCount))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) SetMaxWaitNum(num int) {
 | 
			
		||||
	atomic.AddUint32(&swg.maxCount, uint32(num))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										284
									
								
								vendor/b612.me/starlog/archive.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								vendor/b612.me/starlog/archive.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,284 @@
 | 
			
		||||
package starlog
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"b612.me/staros"
 | 
			
		||||
 | 
			
		||||
	"b612.me/starmap"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var archMap starmap.StarMapKV
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	archMap = starmap.NewStarMap()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Archive interface {
 | 
			
		||||
	ShouldArchiveNow(string, os.FileInfo) bool
 | 
			
		||||
	NextLogFilePath(string, os.FileInfo) string
 | 
			
		||||
	Interval() int64
 | 
			
		||||
	HookBeforArchive() func(string, os.FileInfo) error
 | 
			
		||||
	HookAfterArchive() func(string, string, os.FileInfo) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type logfileinfo struct {
 | 
			
		||||
	fullpath string
 | 
			
		||||
	pointer  *os.File
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetLogFile(path string, logger *StarLogger, appendMode bool) error {
 | 
			
		||||
	var fileMode int
 | 
			
		||||
	if appendMode {
 | 
			
		||||
		fileMode = os.O_APPEND | os.O_CREATE | os.O_WRONLY
 | 
			
		||||
	} else {
 | 
			
		||||
		fileMode = os.O_CREATE | os.O_WRONLY | os.O_TRUNC
 | 
			
		||||
	}
 | 
			
		||||
	fullpath, err := filepath.Abs(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if !appendMode && staros.Exists(fullpath) {
 | 
			
		||||
		os.Remove(fullpath)
 | 
			
		||||
	}
 | 
			
		||||
	fp, err := os.OpenFile(fullpath, fileMode, 0644)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	if archMap.MustGet(logger.logcore.id) != nil {
 | 
			
		||||
		logger.SetSwitching(true)
 | 
			
		||||
		err := archMap.MustGet(logger.logcore.id).(logfileinfo).pointer.Close()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logger.logcore.output = nil
 | 
			
		||||
			logger.SetSwitching(false)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		err = archMap.Delete(logger.logcore.id)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logger.logcore.output = nil
 | 
			
		||||
			logger.SetSwitching(false)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = archMap.Store(logger.logcore.id, logfileinfo{
 | 
			
		||||
		fullpath: fullpath,
 | 
			
		||||
		pointer:  fp,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fp.Close()
 | 
			
		||||
		logger.logcore.output = nil
 | 
			
		||||
		logger.SetSwitching(false)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	logger.SetSwitching(true)
 | 
			
		||||
	logger.logcore.output = fp
 | 
			
		||||
	logger.SetSwitching(false)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CloseWithSwitching(logger *StarLogger) error {
 | 
			
		||||
	if archMap.MustGet(logger.logcore.id) != nil {
 | 
			
		||||
		logger.SetSwitching(true)
 | 
			
		||||
		err := archMap.MustGet(logger.logcore.id).(logfileinfo).pointer.Close()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logger.logcore.output = nil
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		err = archMap.Delete(logger.logcore.id)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Close(logger *StarLogger) error {
 | 
			
		||||
	defer logger.SetSwitching(false)
 | 
			
		||||
	return CloseWithSwitching(logger)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetLogFileInfo(logger *StarLogger) (os.FileInfo, error) {
 | 
			
		||||
	if archMap.MustGet(logger.logcore.id) != nil {
 | 
			
		||||
		return archMap.MustGet(logger.logcore.id).(logfileinfo).pointer.Stat()
 | 
			
		||||
	}
 | 
			
		||||
	return nil, errors.New("logger don't have a register logfile")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StartArchive(logger *StarLogger, arch Archive) error {
 | 
			
		||||
	if archMap.MustGet("arch"+logger.logcore.id) != nil {
 | 
			
		||||
		return errors.New("already running")
 | 
			
		||||
	}
 | 
			
		||||
	stopChan := make(chan int)
 | 
			
		||||
	archMap.Store("arch"+logger.logcore.id, stopChan)
 | 
			
		||||
	go func(stopChan chan int, arch Archive, logger *StarLogger) {
 | 
			
		||||
		for {
 | 
			
		||||
			select {
 | 
			
		||||
			case <-stopChan:
 | 
			
		||||
				return
 | 
			
		||||
			case <-time.After(time.Second * time.Duration(arch.Interval())):
 | 
			
		||||
			}
 | 
			
		||||
			fileinfo, err := GetLogFileInfo(logger)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				logger.Errorf("cannot get log file info,reason is %v\n", err)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if archMap.MustGet(logger.logcore.id) == nil {
 | 
			
		||||
				logger.Errorf("cannot get log core info from the map:no such keys\n")
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			fullpath := archMap.MustGet(logger.logcore.id).(logfileinfo).fullpath
 | 
			
		||||
			if !arch.ShouldArchiveNow(fullpath, fileinfo) {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			newLogPath := arch.NextLogFilePath(fullpath, fileinfo)
 | 
			
		||||
			if arch.HookBeforArchive() != nil {
 | 
			
		||||
				if err := arch.HookBeforArchive()(fullpath, fileinfo); err != nil {
 | 
			
		||||
					logger.Errorf("error occur while executing hook before archive,detail is %v\n", err)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err := SetLogFile(newLogPath, logger, false); err != nil {
 | 
			
		||||
				logger.Errorf("error occur while executing coverting new log file,detail is %v\n", err)
 | 
			
		||||
				continue
 | 
			
		||||
			} else {
 | 
			
		||||
				logger.Debugln("Set Log Success")
 | 
			
		||||
			}
 | 
			
		||||
			fileinfo, err = GetLogFileInfo(logger)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				logger.Errorf("cannot get new log core info from the map:no such keys\n")
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if arch.HookAfterArchive() != nil {
 | 
			
		||||
				if err := arch.HookAfterArchive()(fullpath, newLogPath, fileinfo); err != nil {
 | 
			
		||||
					logger.Errorf("error occur while executing hook after archive,detail is %v\n", err)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}(stopChan, arch, logger)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsArchiveRun(logger *StarLogger) bool {
 | 
			
		||||
	if archMap.MustGet("arch"+logger.logcore.id) == nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StopArchive(logger *StarLogger) {
 | 
			
		||||
	if archMap.MustGet("arch"+logger.logcore.id) == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	archMap.MustGet("arch" + logger.logcore.id).(chan int) <- 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ArchiveByDate struct {
 | 
			
		||||
	interval         int64
 | 
			
		||||
	checkInterval    int64
 | 
			
		||||
	newFileNameStyle string
 | 
			
		||||
	hookBefor        func(string, os.FileInfo) error
 | 
			
		||||
	hookAfter        func(string, string, os.FileInfo) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveByDate) ShouldArchiveNow(fullpath string, info os.FileInfo) bool {
 | 
			
		||||
	if time.Now().Unix()-staros.GetFileCreationTime(info).Unix() > abd.interval {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveByDate) NextLogFilePath(oldpath string, info os.FileInfo) string {
 | 
			
		||||
	dir := filepath.Dir(oldpath)
 | 
			
		||||
	newName := time.Now().Format(abd.newFileNameStyle)
 | 
			
		||||
	return filepath.Join(dir, newName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveByDate) Interval() int64 {
 | 
			
		||||
	return abd.checkInterval
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveByDate) HookBeforArchive() func(string, os.FileInfo) error {
 | 
			
		||||
 | 
			
		||||
	return abd.hookBefor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveByDate) HookAfterArchive() func(string, string, os.FileInfo) error {
 | 
			
		||||
	return abd.hookAfter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveByDate) SetHookBeforArchive(f func(string, os.FileInfo) error) {
 | 
			
		||||
 | 
			
		||||
	abd.hookBefor = f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveByDate) SetHookAfterArchive(f func(string, string, os.FileInfo) error) {
 | 
			
		||||
	abd.hookAfter = f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewArchiveByDate(archInterval int64, checkInterval int64, fileStyle string, hookbefor func(string, os.FileInfo) error, hookafter func(string, string, os.FileInfo) error) *ArchiveByDate {
 | 
			
		||||
	return &ArchiveByDate{
 | 
			
		||||
		interval:         archInterval,
 | 
			
		||||
		checkInterval:    checkInterval,
 | 
			
		||||
		newFileNameStyle: fileStyle,
 | 
			
		||||
		hookBefor:        hookbefor,
 | 
			
		||||
		hookAfter:        hookafter,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ArchiveBySize struct {
 | 
			
		||||
	size             int64
 | 
			
		||||
	checkInterval    int64
 | 
			
		||||
	newFileNameStyle string
 | 
			
		||||
	hookBefor        func(string, os.FileInfo) error
 | 
			
		||||
	hookAfter        func(string, string, os.FileInfo) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveBySize) ShouldArchiveNow(fullpath string, info os.FileInfo) bool {
 | 
			
		||||
	if info.Size() > abd.size {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveBySize) NextLogFilePath(oldpath string, info os.FileInfo) string {
 | 
			
		||||
	dir := filepath.Dir(oldpath)
 | 
			
		||||
	newName := time.Now().Format(abd.newFileNameStyle)
 | 
			
		||||
	return filepath.Join(dir, newName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveBySize) Interval() int64 {
 | 
			
		||||
	return abd.checkInterval
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveBySize) HookBeforArchive() func(string, os.FileInfo) error {
 | 
			
		||||
 | 
			
		||||
	return abd.hookBefor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveBySize) HookAfterArchive() func(string, string, os.FileInfo) error {
 | 
			
		||||
	return abd.hookAfter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveBySize) SetHookBeforArchive(f func(string, os.FileInfo) error) {
 | 
			
		||||
 | 
			
		||||
	abd.hookBefor = f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (abd *ArchiveBySize) SetHookAfterArchive(f func(string, string, os.FileInfo) error) {
 | 
			
		||||
	abd.hookAfter = f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewArchiveBySize(size int64, checkInterval int64, fileStyle string, hookbefor func(string, os.FileInfo) error, hookafter func(string, string, os.FileInfo) error) *ArchiveBySize {
 | 
			
		||||
	return &ArchiveBySize{
 | 
			
		||||
		size:             size,
 | 
			
		||||
		checkInterval:    checkInterval,
 | 
			
		||||
		newFileNameStyle: fileStyle,
 | 
			
		||||
		hookBefor:        hookbefor,
 | 
			
		||||
		hookAfter:        hookafter,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										603
									
								
								vendor/b612.me/starlog/color.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										603
									
								
								vendor/b612.me/starlog/color.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,603 @@
 | 
			
		||||
package starlog
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"b612.me/starlog/colorable"
 | 
			
		||||
	"b612.me/starlog/isatty"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// NoColor defines if the output is colorized or not. It's dynamically set to
 | 
			
		||||
	// false or true based on the stdout's file descriptor referring to a terminal
 | 
			
		||||
	// or not. This is a global option and affects all colors. For more control
 | 
			
		||||
	// over each color block use the methods DisableColor() individually.
 | 
			
		||||
	NoColor = os.Getenv("TERM") == "dumb" ||
 | 
			
		||||
		(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
 | 
			
		||||
 | 
			
		||||
	// Output defines the standard output of the print functions. By default
 | 
			
		||||
	// os.Stdout is used.
 | 
			
		||||
	Output = colorable.NewColorableStdout()
 | 
			
		||||
 | 
			
		||||
	// Error defines a color supporting writer for os.Stderr.
 | 
			
		||||
	Errors = colorable.NewColorableStderr()
 | 
			
		||||
 | 
			
		||||
	// colorsCache is used to reduce the count of created Color objects and
 | 
			
		||||
	// allows to reuse already created objects with required Attr.
 | 
			
		||||
	colorsCache   = make(map[Attr]*Color)
 | 
			
		||||
	colorsCacheMu sync.Mutex // protects colorsCache
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Color defines a custom color object which is defined by SGR parameters.
 | 
			
		||||
type Color struct {
 | 
			
		||||
	params  []Attr
 | 
			
		||||
	noColor *bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Attr defines a single SGR Code
 | 
			
		||||
type Attr int
 | 
			
		||||
 | 
			
		||||
const escape = "\x1b"
 | 
			
		||||
 | 
			
		||||
// Base attributes
 | 
			
		||||
const (
 | 
			
		||||
	Reset Attr = iota
 | 
			
		||||
	Bold
 | 
			
		||||
	Faint
 | 
			
		||||
	Italic
 | 
			
		||||
	Underline
 | 
			
		||||
	BlinkSlow
 | 
			
		||||
	BlinkRapid
 | 
			
		||||
	ReverseVideo
 | 
			
		||||
	Concealed
 | 
			
		||||
	CrossedOut
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Foreground text colors
 | 
			
		||||
const (
 | 
			
		||||
	FgBlack Attr = iota + 30
 | 
			
		||||
	FgRed
 | 
			
		||||
	FgGreen
 | 
			
		||||
	FgYellow
 | 
			
		||||
	FgBlue
 | 
			
		||||
	FgMagenta
 | 
			
		||||
	FgCyan
 | 
			
		||||
	FgWhite
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Foreground Hi-Intensity text colors
 | 
			
		||||
const (
 | 
			
		||||
	FgHiBlack Attr = iota + 90
 | 
			
		||||
	FgHiRed
 | 
			
		||||
	FgHiGreen
 | 
			
		||||
	FgHiYellow
 | 
			
		||||
	FgHiBlue
 | 
			
		||||
	FgHiMagenta
 | 
			
		||||
	FgHiCyan
 | 
			
		||||
	FgHiWhite
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Background text colors
 | 
			
		||||
const (
 | 
			
		||||
	BgBlack Attr = iota + 40
 | 
			
		||||
	BgRed
 | 
			
		||||
	BgGreen
 | 
			
		||||
	BgYellow
 | 
			
		||||
	BgBlue
 | 
			
		||||
	BgMagenta
 | 
			
		||||
	BgCyan
 | 
			
		||||
	BgWhite
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Background Hi-Intensity text colors
 | 
			
		||||
const (
 | 
			
		||||
	BgHiBlack Attr = iota + 100
 | 
			
		||||
	BgHiRed
 | 
			
		||||
	BgHiGreen
 | 
			
		||||
	BgHiYellow
 | 
			
		||||
	BgHiBlue
 | 
			
		||||
	BgHiMagenta
 | 
			
		||||
	BgHiCyan
 | 
			
		||||
	BgHiWhite
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// New returns a newly created color object.
 | 
			
		||||
func NewColor(value ...Attr) *Color {
 | 
			
		||||
	c := &Color{params: make([]Attr, 0)}
 | 
			
		||||
	c.Add(value...)
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets the given parameters immediately. It will change the color of
 | 
			
		||||
// output with the given SGR parameters until color.Unset() is called.
 | 
			
		||||
func Set(p ...Attr) *Color {
 | 
			
		||||
	c := NewColor(p...)
 | 
			
		||||
	c.Set()
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Unset resets all escape attributes and clears the output. Usually should
 | 
			
		||||
// be called after Set().
 | 
			
		||||
func Unset() {
 | 
			
		||||
	if NoColor {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(Output, "%s[%dm", escape, Reset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets the SGR sequence.
 | 
			
		||||
func (c *Color) Set() *Color {
 | 
			
		||||
	if c.isNoColorSet() {
 | 
			
		||||
		return c
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(Output, c.format())
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Color) unset() {
 | 
			
		||||
	if c.isNoColorSet() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Unset()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Color) setWriter(w io.Writer) *Color {
 | 
			
		||||
	if c.isNoColorSet() {
 | 
			
		||||
		return c
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(w, c.format())
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Color) unsetWriter(w io.Writer) {
 | 
			
		||||
	if c.isNoColorSet() {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if NoColor {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(w, "%s[%dm", escape, Reset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add is used to chain SGR parameters. Use as many as parameters to combine
 | 
			
		||||
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
 | 
			
		||||
func (c *Color) Add(value ...Attr) *Color {
 | 
			
		||||
	c.params = append(c.params, value...)
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Color) prepend(value Attr) {
 | 
			
		||||
	c.params = append(c.params, 0)
 | 
			
		||||
	copy(c.params[1:], c.params[0:])
 | 
			
		||||
	c.params[0] = value
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fprint formats using the default formats for its operands and writes to w.
 | 
			
		||||
// Spaces are added between operands when neither is a string.
 | 
			
		||||
// It returns the number of bytes written and any write error encountered.
 | 
			
		||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
 | 
			
		||||
// type *os.File.
 | 
			
		||||
func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
 | 
			
		||||
	c.setWriter(w)
 | 
			
		||||
	defer c.unsetWriter(w)
 | 
			
		||||
 | 
			
		||||
	return fmt.Fprint(w, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Print formats using the default formats for its operands and writes to
 | 
			
		||||
// standard output. Spaces are added between operands when neither is a
 | 
			
		||||
// string. It returns the number of bytes written and any write error
 | 
			
		||||
// encountered. This is the standard fmt.Print() method wrapped with the given
 | 
			
		||||
// color.
 | 
			
		||||
func (c *Color) Print(a ...interface{}) (n int, err error) {
 | 
			
		||||
	c.Set()
 | 
			
		||||
	defer c.unset()
 | 
			
		||||
 | 
			
		||||
	return fmt.Fprint(Output, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fprintf formats according to a format specifier and writes to w.
 | 
			
		||||
// It returns the number of bytes written and any write error encountered.
 | 
			
		||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
 | 
			
		||||
// type *os.File.
 | 
			
		||||
func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
 | 
			
		||||
	c.setWriter(w)
 | 
			
		||||
	defer c.unsetWriter(w)
 | 
			
		||||
 | 
			
		||||
	return fmt.Fprintf(w, format, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Printf formats according to a format specifier and writes to standard output.
 | 
			
		||||
// It returns the number of bytes written and any write error encountered.
 | 
			
		||||
// This is the standard fmt.Printf() method wrapped with the given color.
 | 
			
		||||
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
 | 
			
		||||
	c.Set()
 | 
			
		||||
	defer c.unset()
 | 
			
		||||
 | 
			
		||||
	return fmt.Fprintf(Output, format, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fprintln formats using the default formats for its operands and writes to w.
 | 
			
		||||
// Spaces are always added between operands and a newline is appended.
 | 
			
		||||
// On Windows, users should wrap w with colorable.NewColorable() if w is of
 | 
			
		||||
// type *os.File.
 | 
			
		||||
func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
 | 
			
		||||
	c.setWriter(w)
 | 
			
		||||
	defer c.unsetWriter(w)
 | 
			
		||||
 | 
			
		||||
	return fmt.Fprintln(w, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Println formats using the default formats for its operands and writes to
 | 
			
		||||
// standard output. Spaces are always added between operands and a newline is
 | 
			
		||||
// appended. It returns the number of bytes written and any write error
 | 
			
		||||
// encountered. This is the standard fmt.Print() method wrapped with the given
 | 
			
		||||
// color.
 | 
			
		||||
func (c *Color) Println(a ...interface{}) (n int, err error) {
 | 
			
		||||
	c.Set()
 | 
			
		||||
	defer c.unset()
 | 
			
		||||
 | 
			
		||||
	return fmt.Fprintln(Output, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sprint is just like Print, but returns a string instead of printing it.
 | 
			
		||||
func (c *Color) Sprint(a ...interface{}) string {
 | 
			
		||||
	return c.wrap(fmt.Sprint(a...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sprintln is just like Println, but returns a string instead of printing it.
 | 
			
		||||
func (c *Color) Sprintln(a ...interface{}) string {
 | 
			
		||||
	return c.wrap(fmt.Sprintln(a...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sprintf is just like Printf, but returns a string instead of printing it.
 | 
			
		||||
func (c *Color) Sprintf(format string, a ...interface{}) string {
 | 
			
		||||
	return c.wrap(fmt.Sprintf(format, a...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FprintFunc returns a new function that prints the passed arguments as
 | 
			
		||||
// colorized with color.Fprint().
 | 
			
		||||
func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
 | 
			
		||||
	return func(w io.Writer, a ...interface{}) {
 | 
			
		||||
		c.Fprint(w, a...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrintFunc returns a new function that prints the passed arguments as
 | 
			
		||||
// colorized with color.Print().
 | 
			
		||||
func (c *Color) PrintFunc() func(a ...interface{}) {
 | 
			
		||||
	return func(a ...interface{}) {
 | 
			
		||||
		c.Print(a...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FprintfFunc returns a new function that prints the passed arguments as
 | 
			
		||||
// colorized with color.Fprintf().
 | 
			
		||||
func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
 | 
			
		||||
	return func(w io.Writer, format string, a ...interface{}) {
 | 
			
		||||
		c.Fprintf(w, format, a...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrintfFunc returns a new function that prints the passed arguments as
 | 
			
		||||
// colorized with color.Printf().
 | 
			
		||||
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
 | 
			
		||||
	return func(format string, a ...interface{}) {
 | 
			
		||||
		c.Printf(format, a...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FprintlnFunc returns a new function that prints the passed arguments as
 | 
			
		||||
// colorized with color.Fprintln().
 | 
			
		||||
func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
 | 
			
		||||
	return func(w io.Writer, a ...interface{}) {
 | 
			
		||||
		c.Fprintln(w, a...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PrintlnFunc returns a new function that prints the passed arguments as
 | 
			
		||||
// colorized with color.Println().
 | 
			
		||||
func (c *Color) PrintlnFunc() func(a ...interface{}) {
 | 
			
		||||
	return func(a ...interface{}) {
 | 
			
		||||
		c.Println(a...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SprintFunc returns a new function that returns colorized strings for the
 | 
			
		||||
// given arguments with fmt.Sprint(). Useful to put into or mix into other
 | 
			
		||||
// string. Windows users should use this in conjunction with color.Output, example:
 | 
			
		||||
//
 | 
			
		||||
//	put := New(FgYellow).SprintFunc()
 | 
			
		||||
//	fmt.Fprintf(color.Output, "This is a %s", put("warning"))
 | 
			
		||||
func (c *Color) SprintFunc() func(a ...interface{}) string {
 | 
			
		||||
	return func(a ...interface{}) string {
 | 
			
		||||
		return c.wrap(fmt.Sprint(a...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SprintfFunc returns a new function that returns colorized strings for the
 | 
			
		||||
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
 | 
			
		||||
// string. Windows users should use this in conjunction with color.Output.
 | 
			
		||||
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
 | 
			
		||||
	return func(format string, a ...interface{}) string {
 | 
			
		||||
		return c.wrap(fmt.Sprintf(format, a...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SprintlnFunc returns a new function that returns colorized strings for the
 | 
			
		||||
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
 | 
			
		||||
// string. Windows users should use this in conjunction with color.Output.
 | 
			
		||||
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
 | 
			
		||||
	return func(a ...interface{}) string {
 | 
			
		||||
		return c.wrap(fmt.Sprintln(a...))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m"
 | 
			
		||||
// an example output might be: "1;36" -> bold cyan
 | 
			
		||||
func (c *Color) sequence() string {
 | 
			
		||||
	format := make([]string, len(c.params))
 | 
			
		||||
	for i, v := range c.params {
 | 
			
		||||
		format[i] = strconv.Itoa(int(v))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return strings.Join(format, ";")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// wrap wraps the s string with the colors attributes. The string is ready to
 | 
			
		||||
// be printed.
 | 
			
		||||
func (c *Color) wrap(s string) string {
 | 
			
		||||
	if c.isNoColorSet() {
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.format() + s + c.unformat()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Color) format() string {
 | 
			
		||||
	return fmt.Sprintf("%s[%sm", escape, c.sequence())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Color) unformat() string {
 | 
			
		||||
	return fmt.Sprintf("%s[%dm", escape, Reset)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DisableColor disables the color output. Useful to not change any existing
 | 
			
		||||
// code and still being able to output. Can be used for flags like
 | 
			
		||||
// "--no-color". To enable back use EnableColor() method.
 | 
			
		||||
func (c *Color) DisableColor() {
 | 
			
		||||
	c.noColor = boolPtr(true)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableColor enables the color output. Use it in conjunction with
 | 
			
		||||
// DisableColor(). Otherwise this method has no side effects.
 | 
			
		||||
func (c *Color) EnableColor() {
 | 
			
		||||
	c.noColor = boolPtr(false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Color) isNoColorSet() bool {
 | 
			
		||||
	// check first if we have user setted action
 | 
			
		||||
	if c.noColor != nil {
 | 
			
		||||
		return *c.noColor
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// if not return the global option, which is disabled by default
 | 
			
		||||
	return NoColor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equals returns a boolean value indicating whether two colors are equal.
 | 
			
		||||
func (c *Color) Equals(c2 *Color) bool {
 | 
			
		||||
	if len(c.params) != len(c2.params) {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, attr := range c.params {
 | 
			
		||||
		if !c2.attrExists(attr) {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Color) attrExists(a Attr) bool {
 | 
			
		||||
	for _, attr := range c.params {
 | 
			
		||||
		if attr == a {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func boolPtr(v bool) *bool {
 | 
			
		||||
	return &v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getCachedColor(p Attr) *Color {
 | 
			
		||||
	colorsCacheMu.Lock()
 | 
			
		||||
	defer colorsCacheMu.Unlock()
 | 
			
		||||
 | 
			
		||||
	c, ok := colorsCache[p]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		c = NewColor(p)
 | 
			
		||||
		colorsCache[p] = c
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func colorPrint(format string, p Attr, a ...interface{}) {
 | 
			
		||||
	c := getCachedColor(p)
 | 
			
		||||
 | 
			
		||||
	if !strings.HasSuffix(format, "\n") {
 | 
			
		||||
		format += "\n"
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(a) == 0 {
 | 
			
		||||
		c.Print(format)
 | 
			
		||||
	} else {
 | 
			
		||||
		c.Printf(format, a...)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func colorString(format string, p Attr, a ...interface{}) string {
 | 
			
		||||
	c := getCachedColor(p)
 | 
			
		||||
 | 
			
		||||
	if len(a) == 0 {
 | 
			
		||||
		return c.SprintFunc()(format)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return c.SprintfFunc()(format, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Black is a convenient helper function to print with black foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) }
 | 
			
		||||
 | 
			
		||||
// Red is a convenient helper function to print with red foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) }
 | 
			
		||||
 | 
			
		||||
// Green is a convenient helper function to print with green foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) }
 | 
			
		||||
 | 
			
		||||
// Yellow is a convenient helper function to print with yellow foreground.
 | 
			
		||||
// A newline is appended to format by default.
 | 
			
		||||
func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) }
 | 
			
		||||
 | 
			
		||||
// Blue is a convenient helper function to print with blue foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) }
 | 
			
		||||
 | 
			
		||||
// Magenta is a convenient helper function to print with magenta foreground.
 | 
			
		||||
// A newline is appended to format by default.
 | 
			
		||||
func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) }
 | 
			
		||||
 | 
			
		||||
// Cyan is a convenient helper function to print with cyan foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) }
 | 
			
		||||
 | 
			
		||||
// White is a convenient helper function to print with white foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) }
 | 
			
		||||
 | 
			
		||||
// BlackString is a convenient helper function to return a string with black
 | 
			
		||||
// foreground.
 | 
			
		||||
func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) }
 | 
			
		||||
 | 
			
		||||
// RedString is a convenient helper function to return a string with red
 | 
			
		||||
// foreground.
 | 
			
		||||
func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) }
 | 
			
		||||
 | 
			
		||||
// GreenString is a convenient helper function to return a string with green
 | 
			
		||||
// foreground.
 | 
			
		||||
func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) }
 | 
			
		||||
 | 
			
		||||
// YellowString is a convenient helper function to return a string with yellow
 | 
			
		||||
// foreground.
 | 
			
		||||
func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) }
 | 
			
		||||
 | 
			
		||||
// BlueString is a convenient helper function to return a string with blue
 | 
			
		||||
// foreground.
 | 
			
		||||
func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) }
 | 
			
		||||
 | 
			
		||||
// MagentaString is a convenient helper function to return a string with magenta
 | 
			
		||||
// foreground.
 | 
			
		||||
func MagentaString(format string, a ...interface{}) string {
 | 
			
		||||
	return colorString(format, FgMagenta, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CyanString is a convenient helper function to return a string with cyan
 | 
			
		||||
// foreground.
 | 
			
		||||
func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) }
 | 
			
		||||
 | 
			
		||||
// WhiteString is a convenient helper function to return a string with white
 | 
			
		||||
// foreground.
 | 
			
		||||
func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) }
 | 
			
		||||
 | 
			
		||||
// HiBlack is a convenient helper function to print with hi-intensity black foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) }
 | 
			
		||||
 | 
			
		||||
// HiRed is a convenient helper function to print with hi-intensity red foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) }
 | 
			
		||||
 | 
			
		||||
// HiGreen is a convenient helper function to print with hi-intensity green foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) }
 | 
			
		||||
 | 
			
		||||
// HiYellow is a convenient helper function to print with hi-intensity yellow foreground.
 | 
			
		||||
// A newline is appended to format by default.
 | 
			
		||||
func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) }
 | 
			
		||||
 | 
			
		||||
// HiBlue is a convenient helper function to print with hi-intensity blue foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) }
 | 
			
		||||
 | 
			
		||||
// HiMagenta is a convenient helper function to print with hi-intensity magenta foreground.
 | 
			
		||||
// A newline is appended to format by default.
 | 
			
		||||
func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) }
 | 
			
		||||
 | 
			
		||||
// HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) }
 | 
			
		||||
 | 
			
		||||
// HiWhite is a convenient helper function to print with hi-intensity white foreground. A
 | 
			
		||||
// newline is appended to format by default.
 | 
			
		||||
func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) }
 | 
			
		||||
 | 
			
		||||
// HiBlackString is a convenient helper function to return a string with hi-intensity black
 | 
			
		||||
// foreground.
 | 
			
		||||
func HiBlackString(format string, a ...interface{}) string {
 | 
			
		||||
	return colorString(format, FgHiBlack, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HiRedString is a convenient helper function to return a string with hi-intensity red
 | 
			
		||||
// foreground.
 | 
			
		||||
func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) }
 | 
			
		||||
 | 
			
		||||
// HiGreenString is a convenient helper function to return a string with hi-intensity green
 | 
			
		||||
// foreground.
 | 
			
		||||
func HiGreenString(format string, a ...interface{}) string {
 | 
			
		||||
	return colorString(format, FgHiGreen, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HiYellowString is a convenient helper function to return a string with hi-intensity yellow
 | 
			
		||||
// foreground.
 | 
			
		||||
func HiYellowString(format string, a ...interface{}) string {
 | 
			
		||||
	return colorString(format, FgHiYellow, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HiBlueString is a convenient helper function to return a string with hi-intensity blue
 | 
			
		||||
// foreground.
 | 
			
		||||
func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) }
 | 
			
		||||
 | 
			
		||||
// HiMagentaString is a convenient helper function to return a string with hi-intensity magenta
 | 
			
		||||
// foreground.
 | 
			
		||||
func HiMagentaString(format string, a ...interface{}) string {
 | 
			
		||||
	return colorString(format, FgHiMagenta, a...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HiCyanString is a convenient helper function to return a string with hi-intensity cyan
 | 
			
		||||
// foreground.
 | 
			
		||||
func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) }
 | 
			
		||||
 | 
			
		||||
// HiWhiteString is a convenient helper function to return a string with hi-intensity white
 | 
			
		||||
// foreground.
 | 
			
		||||
func HiWhiteString(format string, a ...interface{}) string {
 | 
			
		||||
	return colorString(format, FgHiWhite, a...)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										37
									
								
								vendor/b612.me/starlog/colorable/colorable_appengine.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								vendor/b612.me/starlog/colorable/colorable_appengine.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
// +build appengine
 | 
			
		||||
 | 
			
		||||
package colorable
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	_ "b612.me/starlog/isatty"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewColorable returns new instance of Writer which handles escape sequence.
 | 
			
		||||
func NewColorable(file *os.File) io.Writer {
 | 
			
		||||
	if file == nil {
 | 
			
		||||
		panic("nil passed instead of *os.File to NewColorable()")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return file
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
 | 
			
		||||
func NewColorableStdout() io.Writer {
 | 
			
		||||
	return os.Stdout
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
 | 
			
		||||
func NewColorableStderr() io.Writer {
 | 
			
		||||
	return os.Stderr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableColorsStdout enable colors if possible.
 | 
			
		||||
func EnableColorsStdout(enabled *bool) func() {
 | 
			
		||||
	if enabled != nil {
 | 
			
		||||
		*enabled = true
 | 
			
		||||
	}
 | 
			
		||||
	return func() {}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								vendor/b612.me/starlog/colorable/colorable_others.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								vendor/b612.me/starlog/colorable/colorable_others.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
// +build !windows
 | 
			
		||||
// +build !appengine
 | 
			
		||||
 | 
			
		||||
package colorable
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	_ "b612.me/starlog/isatty"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewColorable returns new instance of Writer which handles escape sequence.
 | 
			
		||||
func NewColorable(file *os.File) io.Writer {
 | 
			
		||||
	if file == nil {
 | 
			
		||||
		panic("nil passed instead of *os.File to NewColorable()")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return file
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewColorableStdout returns new instance of Writer which handles escape sequence for stdout.
 | 
			
		||||
func NewColorableStdout() io.Writer {
 | 
			
		||||
	return os.Stdout
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewColorableStderr returns new instance of Writer which handles escape sequence for stderr.
 | 
			
		||||
func NewColorableStderr() io.Writer {
 | 
			
		||||
	return os.Stderr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EnableColorsStdout enable colors if possible.
 | 
			
		||||
func EnableColorsStdout(enabled *bool) func() {
 | 
			
		||||
	if enabled != nil {
 | 
			
		||||
		*enabled = true
 | 
			
		||||
	}
 | 
			
		||||
	return func() {}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1043
									
								
								vendor/b612.me/starlog/colorable/colorable_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1043
									
								
								vendor/b612.me/starlog/colorable/colorable_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										55
									
								
								vendor/b612.me/starlog/colorable/noncolorable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								vendor/b612.me/starlog/colorable/noncolorable.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
package colorable
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NonColorable holds writer but removes escape sequence.
 | 
			
		||||
type NonColorable struct {
 | 
			
		||||
	out io.Writer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewNonColorable returns new instance of Writer which removes escape sequence from Writer.
 | 
			
		||||
func NewNonColorable(w io.Writer) io.Writer {
 | 
			
		||||
	return &NonColorable{out: w}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write writes data on console
 | 
			
		||||
func (w *NonColorable) Write(data []byte) (n int, err error) {
 | 
			
		||||
	er := bytes.NewReader(data)
 | 
			
		||||
	var bw [1]byte
 | 
			
		||||
loop:
 | 
			
		||||
	for {
 | 
			
		||||
		c1, err := er.ReadByte()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			break loop
 | 
			
		||||
		}
 | 
			
		||||
		if c1 != 0x1b {
 | 
			
		||||
			bw[0] = c1
 | 
			
		||||
			w.out.Write(bw[:])
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		c2, err := er.ReadByte()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			break loop
 | 
			
		||||
		}
 | 
			
		||||
		if c2 != 0x5b {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var buf bytes.Buffer
 | 
			
		||||
		for {
 | 
			
		||||
			c, err := er.ReadByte()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				break loop
 | 
			
		||||
			}
 | 
			
		||||
			if ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '@' {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			buf.Write([]byte(string(c)))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return len(data), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										296
									
								
								vendor/b612.me/starlog/core.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								vendor/b612.me/starlog/core.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,296 @@
 | 
			
		||||
package starlog
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func generateCoreLogStr(skip int, logstr string) string {
 | 
			
		||||
	var line int = 0
 | 
			
		||||
	var funcname, fileName string
 | 
			
		||||
	now := time.Now()
 | 
			
		||||
 | 
			
		||||
	pc, fName, codeln, ok := runtime.Caller(skip)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	line = codeln
 | 
			
		||||
	funcname = runtime.FuncForPC(pc).Name()
 | 
			
		||||
	funcname = filepath.Ext(funcname)
 | 
			
		||||
	funcname = strings.TrimPrefix(funcname, ".")
 | 
			
		||||
	fileName = filepath.Base(fName)
 | 
			
		||||
 | 
			
		||||
	y, m, d := now.Date()
 | 
			
		||||
	h, i, s := now.Clock()
 | 
			
		||||
	micro := now.Nanosecond() / 1e3
 | 
			
		||||
	logStr := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d.%06d", y, m, d, h, i, s, micro)
 | 
			
		||||
	logStr += " " + fileName + ":" + strconv.Itoa(line)
 | 
			
		||||
	logStr += " <" + funcname + ">"
 | 
			
		||||
	logStr += " " + logstr
 | 
			
		||||
	return logStr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) build(thread string, isStd bool, isShow bool, handler func([]Attr, string), level int, logDetail string) {
 | 
			
		||||
	logger.mu.Lock()
 | 
			
		||||
	defer logger.mu.Unlock()
 | 
			
		||||
	var skip, line int = 3, 0
 | 
			
		||||
	var funcname, fileName string
 | 
			
		||||
	now := time.Now()
 | 
			
		||||
	if isStd {
 | 
			
		||||
		skip++
 | 
			
		||||
	}
 | 
			
		||||
	if logger.showDeatilFile || logger.showFuncName {
 | 
			
		||||
		pc, fName, codeln, ok := runtime.Caller(skip)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		line = codeln
 | 
			
		||||
		funcname = runtime.FuncForPC(pc).Name()
 | 
			
		||||
		funcname = filepath.Ext(funcname)
 | 
			
		||||
		funcname = strings.TrimPrefix(funcname, ".")
 | 
			
		||||
		fileName = filepath.Base(fName)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	y, m, d := now.Date()
 | 
			
		||||
	h, i, s := now.Clock()
 | 
			
		||||
	micro := now.Nanosecond() / 1e3
 | 
			
		||||
	logStr := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d.%06d", y, m, d, h, i, s, micro)
 | 
			
		||||
	var cenStr string
 | 
			
		||||
	if logger.showDeatilFile {
 | 
			
		||||
		cenStr += " " + fileName + ":" + strconv.Itoa(line)
 | 
			
		||||
	}
 | 
			
		||||
	if logger.showFuncName {
 | 
			
		||||
		cenStr += " <" + funcname + ">"
 | 
			
		||||
	}
 | 
			
		||||
	if logger.showThread {
 | 
			
		||||
		cenStr += " |" + thread + "|"
 | 
			
		||||
	}
 | 
			
		||||
	if logger.showLevel {
 | 
			
		||||
		cenStr += " " + `[` + levels[level] + `]`
 | 
			
		||||
	}
 | 
			
		||||
	if !logger.showColor || !logger.onlyColorLevel {
 | 
			
		||||
		logStr += cenStr + " " + logDetail
 | 
			
		||||
	} else {
 | 
			
		||||
		logStr += logger.colorMe[level].Sprint(cenStr) + " " + logDetail
 | 
			
		||||
	}
 | 
			
		||||
	if isShow {
 | 
			
		||||
		if !logger.showColor {
 | 
			
		||||
			fmt.Print(logStr)
 | 
			
		||||
		} else if !logger.onlyColorLevel {
 | 
			
		||||
			//logcolor := NewColor(logger.colorList[level]...)
 | 
			
		||||
			logger.colorMe[level].Fprint(stdScreen, logStr)
 | 
			
		||||
		} else {
 | 
			
		||||
			fmt.Fprint(stdScreen, logStr)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if handler != nil {
 | 
			
		||||
		stacks.Push(logTransfer{
 | 
			
		||||
			handlerFunc: handler,
 | 
			
		||||
			colors:      logger.colorList[level],
 | 
			
		||||
			logStr:      logStr,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	if !logger.stopWriter {
 | 
			
		||||
		logger.write(logStr)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) write(logStr string) {
 | 
			
		||||
	if logger.output == nil || logger.stopWriter {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	var count int = 0
 | 
			
		||||
	for logger.switching {
 | 
			
		||||
		time.Sleep(time.Millisecond * 100)
 | 
			
		||||
		count++
 | 
			
		||||
		if count > 50 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if logger.output == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	logger.output.Write([]byte(logStr))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) print(str ...interface{}) string {
 | 
			
		||||
	return fmt.Sprint(str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) printf(format string, str ...interface{}) string {
 | 
			
		||||
	return fmt.Sprintf(format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) println(str ...interface{}) string {
 | 
			
		||||
	return fmt.Sprintln(str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Debug(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvDebug, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Debugf(thread string, isStd bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvDebug, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Debugln(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvDebug, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Info(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvInfo, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Infof(thread string, isStd bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvInfo, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Infoln(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvInfo, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Notice(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvNotice, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Noticef(thread string, isStd bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvNotice, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Noticeln(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvNotice, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Warning(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvWarning, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Warningf(thread string, isStd bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvWarning, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Warningln(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvWarning, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Error(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvError, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Errorf(thread string, isStd bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvError, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Errorln(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvError, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Critical(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvCritical, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Criticalf(thread string, isStd bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvCritical, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Criticalln(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvCritical, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Fatal(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvFatal, strs)
 | 
			
		||||
	os.Exit(9)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Fatalf(thread string, isStd bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvFatal, strs)
 | 
			
		||||
	os.Exit(9)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Fatalln(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvFatal, strs)
 | 
			
		||||
	os.Exit(9)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Panic(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvPanic, strs)
 | 
			
		||||
	panic(str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Panicf(thread string, isStd bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvPanic, strs)
 | 
			
		||||
	panic(fmt.Sprintf(format, str...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Panicln(thread string, isStd bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, logger.showStd, handler, LvPanic, strs)
 | 
			
		||||
	panic(fmt.Sprintln(str...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Print(thread string, isStd bool, isShow bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	if isShow {
 | 
			
		||||
		fmt.Print(strs)
 | 
			
		||||
	}
 | 
			
		||||
	logger.write(strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Printf(thread string, isStd bool, isShow bool, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	if isShow {
 | 
			
		||||
		fmt.Print(strs)
 | 
			
		||||
	}
 | 
			
		||||
	logger.write(strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Println(thread string, isStd bool, isShow bool, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	if isShow {
 | 
			
		||||
		fmt.Print(strs)
 | 
			
		||||
	}
 | 
			
		||||
	logger.write(strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Log(thread string, isStd bool, isShow bool, level int, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	logger.build(thread, isStd, isShow, handler, level, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Logf(thread string, isStd bool, isShow bool, level int, handler func([]Attr, string), format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	logger.build(thread, isStd, isShow, handler, level, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *starlog) Logln(thread string, isStd bool, isShow bool, level int, handler func([]Attr, string), str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	logger.build(thread, isStd, isShow, handler, level, strs)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/b612.me/starlog/isatty/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/b612.me/starlog/isatty/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
// Package isatty implements interface to isatty
 | 
			
		||||
package isatty
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/b612.me/starlog/isatty/isatty_bsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/b612.me/starlog/isatty/isatty_bsd.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
// +build darwin freebsd openbsd netbsd dragonfly
 | 
			
		||||
// +build !appengine
 | 
			
		||||
 | 
			
		||||
package isatty
 | 
			
		||||
 | 
			
		||||
import "golang.org/x/sys/unix"
 | 
			
		||||
 | 
			
		||||
// IsTerminal return true if the file descriptor is terminal.
 | 
			
		||||
func IsTerminal(fd uintptr) bool {
 | 
			
		||||
	_, err := unix.IoctlGetTermios(int(fd), unix.TIOCGETA)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
 | 
			
		||||
// terminal. This is also always false on this environment.
 | 
			
		||||
func IsCygwinTerminal(fd uintptr) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/b612.me/starlog/isatty/isatty_others.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								vendor/b612.me/starlog/isatty/isatty_others.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
// +build appengine js nacl wasm
 | 
			
		||||
 | 
			
		||||
package isatty
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if the file descriptor is terminal which
 | 
			
		||||
// is always false on js and appengine classic which is a sandboxed PaaS.
 | 
			
		||||
func IsTerminal(fd uintptr) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
 | 
			
		||||
// terminal. This is also always false on this environment.
 | 
			
		||||
func IsCygwinTerminal(fd uintptr) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/b612.me/starlog/isatty/isatty_plan9.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/b612.me/starlog/isatty/isatty_plan9.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
// +build plan9
 | 
			
		||||
 | 
			
		||||
package isatty
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if the given file descriptor is a terminal.
 | 
			
		||||
func IsTerminal(fd uintptr) bool {
 | 
			
		||||
	path, err := syscall.Fd2path(int(fd))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return path == "/dev/cons" || path == "/mnt/term/dev/cons"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
 | 
			
		||||
// terminal. This is also always false on this environment.
 | 
			
		||||
func IsCygwinTerminal(fd uintptr) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/b612.me/starlog/isatty/isatty_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/b612.me/starlog/isatty/isatty_solaris.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
// +build solaris
 | 
			
		||||
// +build !appengine
 | 
			
		||||
 | 
			
		||||
package isatty
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// IsTerminal returns true if the given file descriptor is a terminal.
 | 
			
		||||
// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c
 | 
			
		||||
func IsTerminal(fd uintptr) bool {
 | 
			
		||||
	var termio unix.Termio
 | 
			
		||||
	err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
 | 
			
		||||
// terminal. This is also always false on this environment.
 | 
			
		||||
func IsCygwinTerminal(fd uintptr) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								vendor/b612.me/starlog/isatty/isatty_tcgets.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								vendor/b612.me/starlog/isatty/isatty_tcgets.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
// +build linux aix
 | 
			
		||||
// +build !appengine
 | 
			
		||||
 | 
			
		||||
package isatty
 | 
			
		||||
 | 
			
		||||
import "golang.org/x/sys/unix"
 | 
			
		||||
 | 
			
		||||
// IsTerminal return true if the file descriptor is terminal.
 | 
			
		||||
func IsTerminal(fd uintptr) bool {
 | 
			
		||||
	_, err := unix.IoctlGetTermios(int(fd), unix.TCGETS)
 | 
			
		||||
	return err == nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2
 | 
			
		||||
// terminal. This is also always false on this environment.
 | 
			
		||||
func IsCygwinTerminal(fd uintptr) bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										125
									
								
								vendor/b612.me/starlog/isatty/isatty_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								vendor/b612.me/starlog/isatty/isatty_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,125 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
// +build !appengine
 | 
			
		||||
 | 
			
		||||
package isatty
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unicode/utf16"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	objectNameInfo uintptr = 1
 | 
			
		||||
	fileNameInfo           = 2
 | 
			
		||||
	fileTypePipe           = 3
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	kernel32                         = syscall.NewLazyDLL("kernel32.dll")
 | 
			
		||||
	ntdll                            = syscall.NewLazyDLL("ntdll.dll")
 | 
			
		||||
	procGetConsoleMode               = kernel32.NewProc("GetConsoleMode")
 | 
			
		||||
	procGetFileInformationByHandleEx = kernel32.NewProc("GetFileInformationByHandleEx")
 | 
			
		||||
	procGetFileType                  = kernel32.NewProc("GetFileType")
 | 
			
		||||
	procNtQueryObject                = ntdll.NewProc("NtQueryObject")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	// Check if GetFileInformationByHandleEx is available.
 | 
			
		||||
	if procGetFileInformationByHandleEx.Find() != nil {
 | 
			
		||||
		procGetFileInformationByHandleEx = nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsTerminal return true if the file descriptor is terminal.
 | 
			
		||||
func IsTerminal(fd uintptr) bool {
 | 
			
		||||
	var st uint32
 | 
			
		||||
	r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, fd, uintptr(unsafe.Pointer(&st)), 0)
 | 
			
		||||
	return r != 0 && e == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check pipe name is used for cygwin/msys2 pty.
 | 
			
		||||
// Cygwin/MSYS2 PTY has a name like:
 | 
			
		||||
//   \{cygwin,msys}-XXXXXXXXXXXXXXXX-ptyN-{from,to}-master
 | 
			
		||||
func isCygwinPipeName(name string) bool {
 | 
			
		||||
	token := strings.Split(name, "-")
 | 
			
		||||
	if len(token) < 5 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if token[0] != `\msys` &&
 | 
			
		||||
		token[0] != `\cygwin` &&
 | 
			
		||||
		token[0] != `\Device\NamedPipe\msys` &&
 | 
			
		||||
		token[0] != `\Device\NamedPipe\cygwin` {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if token[1] == "" {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !strings.HasPrefix(token[2], "pty") {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if token[3] != `from` && token[3] != `to` {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if token[4] != "master" {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler
 | 
			
		||||
// since GetFileInformationByHandleEx is not avilable under windows Vista and still some old fashion
 | 
			
		||||
// guys are using Windows XP, this is a workaround for those guys, it will also work on system from
 | 
			
		||||
// Windows vista to 10
 | 
			
		||||
// see https://stackoverflow.com/a/18792477 for details
 | 
			
		||||
func getFileNameByHandle(fd uintptr) (string, error) {
 | 
			
		||||
	if procNtQueryObject == nil {
 | 
			
		||||
		return "", errors.New("ntdll.dll: NtQueryObject not supported")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var buf [4 + syscall.MAX_PATH]uint16
 | 
			
		||||
	var result int
 | 
			
		||||
	r, _, e := syscall.Syscall6(procNtQueryObject.Addr(), 5,
 | 
			
		||||
		fd, objectNameInfo, uintptr(unsafe.Pointer(&buf)), uintptr(2*len(buf)), uintptr(unsafe.Pointer(&result)), 0)
 | 
			
		||||
	if r != 0 {
 | 
			
		||||
		return "", e
 | 
			
		||||
	}
 | 
			
		||||
	return string(utf16.Decode(buf[4 : 4+buf[0]/2])), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsCygwinTerminal() return true if the file descriptor is a cygwin or msys2
 | 
			
		||||
// terminal.
 | 
			
		||||
func IsCygwinTerminal(fd uintptr) bool {
 | 
			
		||||
	if procGetFileInformationByHandleEx == nil {
 | 
			
		||||
		name, err := getFileNameByHandle(fd)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		return isCygwinPipeName(name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Cygwin/msys's pty is a pipe.
 | 
			
		||||
	ft, _, e := syscall.Syscall(procGetFileType.Addr(), 1, fd, 0, 0)
 | 
			
		||||
	if ft != fileTypePipe || e != 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var buf [2 + syscall.MAX_PATH]uint16
 | 
			
		||||
	r, _, e := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(),
 | 
			
		||||
		4, fd, fileNameInfo, uintptr(unsafe.Pointer(&buf)),
 | 
			
		||||
		uintptr(len(buf)*2), 0, 0)
 | 
			
		||||
	if r == 0 || e != 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l := *(*uint32)(unsafe.Pointer(&buf))
 | 
			
		||||
	return isCygwinPipeName(string(utf16.Decode(buf[2 : 2+l/2])))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										325
									
								
								vendor/b612.me/starlog/standed.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								vendor/b612.me/starlog/standed.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,325 @@
 | 
			
		||||
package starlog
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/starmap"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var Std *StarLogger
 | 
			
		||||
var stdmu sync.Mutex
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	stacks = starmap.NewStarStack(1024)
 | 
			
		||||
	rand.Seed(time.Now().UnixNano())
 | 
			
		||||
	stackStopChan = make(chan int)
 | 
			
		||||
	StartStacks()
 | 
			
		||||
	Std = NewStarlog(nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetShowColor(val bool) {
 | 
			
		||||
	Std.SetShowColor(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetShowColor() bool {
 | 
			
		||||
	return Std.GetShowColor()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetLevelColor(level int, color []Attr) {
 | 
			
		||||
	Std.SetLevelColor(level, color)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetLevelColor(level int) []Attr {
 | 
			
		||||
	return Std.GetLevelColor(level)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Debug(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Debug(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Debugf(format string, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Debugf(format, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Debugln(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Debugln(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Info(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Info(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Infof(format string, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Infof(format, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Infoln(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Infoln(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Notice(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Notice(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Noticef(format string, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Noticef(format, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Noticeln(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Noticeln(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Warning(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Warning(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Warningf(format string, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Warningf(format, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Warningln(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Warningln(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Error(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Error(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Errorf(format string, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Errorf(format, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Errorln(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Errorln(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Critical(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Critical(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Criticalf(format string, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Criticalf(format, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Criticalln(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Criticalln(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Fatal(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Fatal(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Fatalf(format string, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Fatalf(format, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Panicln(str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Fatalln(str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Print(str ...interface{}) {
 | 
			
		||||
	Std.Print(str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Printf(format string, str ...interface{}) {
 | 
			
		||||
	Std.Printf(format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Println(str ...interface{}) {
 | 
			
		||||
	Std.Println(str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Log(isShow bool, level int, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Log(isShow, level, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Logf(isShow bool, level int, format string, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Logf(isShow, level, format, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Logln(isShow bool, level int, str ...interface{}) {
 | 
			
		||||
	stdmu.Lock()
 | 
			
		||||
	defer stdmu.Unlock()
 | 
			
		||||
	Std.isStd = true
 | 
			
		||||
	Std.Logln(isShow, level, str...)
 | 
			
		||||
	Std.isStd = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StdPrint(attr []Attr, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprint(str...)
 | 
			
		||||
	NewColor(attr...).Fprint(stdScreen, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StdPrintf(attr []Attr, format string, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintf(format, str...)
 | 
			
		||||
	NewColor(attr...).Fprint(stdScreen, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StdPrintln(attr []Attr, str ...interface{}) {
 | 
			
		||||
	strs := fmt.Sprintln(str...)
 | 
			
		||||
	NewColor(attr...).Fprint(stdScreen, strs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetWriter(wr io.Writer) {
 | 
			
		||||
	Std.SetWriter(wr)
 | 
			
		||||
}
 | 
			
		||||
func GetWriter() io.Writer {
 | 
			
		||||
	return Std.GetWriter()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetHandler(f func([]Attr, string)) {
 | 
			
		||||
	Std.SetHandler(f)
 | 
			
		||||
}
 | 
			
		||||
func GetHandler() func([]Attr, string) {
 | 
			
		||||
	return Std.GetHandler()
 | 
			
		||||
}
 | 
			
		||||
func SetSwitching(sw bool) {
 | 
			
		||||
	Std.SetSwitching(sw)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetShowOriginFile(val bool) {
 | 
			
		||||
	Std.SetShowOriginFile(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetShowOriginFile() bool {
 | 
			
		||||
	return Std.GetShowOriginFile()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetShowFuncName(val bool) {
 | 
			
		||||
	Std.logcore.showFuncName = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetShowFuncName() bool {
 | 
			
		||||
	return Std.logcore.showFuncName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetShowLevel(val bool) {
 | 
			
		||||
	Std.SetShowLevel(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetShowLevel() bool {
 | 
			
		||||
	return Std.GetShowLevel()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetShowFlag(val bool) {
 | 
			
		||||
	Std.SetShowFlag(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetShowFlag() bool {
 | 
			
		||||
	return Std.GetShowFlag()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetShowStd(val bool) {
 | 
			
		||||
	Std.SetShowStd(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetShowStd() bool {
 | 
			
		||||
	return Std.GetShowStd()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StopWrite() {
 | 
			
		||||
	Std.StopWrite()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func EnbaleWrite() {
 | 
			
		||||
	Std.EnbaleWrite()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsWriteStoed() bool {
 | 
			
		||||
	return Std.IsWriteStoed()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										206
									
								
								vendor/b612.me/starlog/starlog.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								vendor/b612.me/starlog/starlog.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,206 @@
 | 
			
		||||
package starlog
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetShowColor(val bool) {
 | 
			
		||||
	logger.logcore.showColor = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) GetShowColor() bool {
 | 
			
		||||
	return logger.logcore.showColor
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetLevelColor(level int, color []Attr) {
 | 
			
		||||
	logger.logcore.colorList[level] = color
 | 
			
		||||
	logger.logcore.colorMe[level] = NewColor(color...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) GetLevelColor(level int) []Attr {
 | 
			
		||||
	return logger.logcore.colorList[level]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetWriter(wr io.Writer) {
 | 
			
		||||
	logger.logcore.output = wr
 | 
			
		||||
}
 | 
			
		||||
func (logger *StarLogger) GetWriter() io.Writer {
 | 
			
		||||
	return logger.logcore.output
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetHandler(f func([]Attr, string)) {
 | 
			
		||||
	logger.handlerFunc = f
 | 
			
		||||
}
 | 
			
		||||
func (logger *StarLogger) GetHandler() func([]Attr, string) {
 | 
			
		||||
	return logger.handlerFunc
 | 
			
		||||
}
 | 
			
		||||
func (logger *StarLogger) SetSwitching(sw bool) {
 | 
			
		||||
	logger.logcore.switching = sw
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetOnlyColorLevel(ocl bool) {
 | 
			
		||||
	logger.logcore.onlyColorLevel = ocl
 | 
			
		||||
}
 | 
			
		||||
func (logger *StarLogger) GetOnlyColorLevel() bool {
 | 
			
		||||
	return logger.logcore.onlyColorLevel
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetShowOriginFile(val bool) {
 | 
			
		||||
	logger.logcore.showDeatilFile = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) GetShowOriginFile() bool {
 | 
			
		||||
	return logger.logcore.showDeatilFile
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetShowFuncName(val bool) {
 | 
			
		||||
	logger.logcore.showFuncName = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) GetShowFuncName() bool {
 | 
			
		||||
	return logger.logcore.showFuncName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetShowLevel(val bool) {
 | 
			
		||||
	logger.logcore.showLevel = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) GetShowLevel() bool {
 | 
			
		||||
	return logger.logcore.showLevel
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetShowFlag(val bool) {
 | 
			
		||||
	logger.logcore.showThread = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) GetShowFlag() bool {
 | 
			
		||||
	return logger.logcore.showThread
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) SetShowStd(val bool) {
 | 
			
		||||
	logger.logcore.showStd = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) GetShowStd() bool {
 | 
			
		||||
	return logger.logcore.showStd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) StopWrite() {
 | 
			
		||||
	logger.logcore.stopWriter = true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) EnbaleWrite() {
 | 
			
		||||
	logger.logcore.stopWriter = false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) IsWriteStoed() bool {
 | 
			
		||||
	return logger.logcore.stopWriter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Debug(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Debug(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Debugf(format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Debugf(logger.thread, logger.isStd, logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Debugln(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Debugln(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Info(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Info(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Infof(format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Infof(logger.thread, logger.isStd, logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Infoln(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Infoln(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Notice(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Notice(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Noticef(format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Noticef(logger.thread, logger.isStd, logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Noticeln(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Noticeln(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Warning(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Warning(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Warningf(format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Warningf(logger.thread, logger.isStd, logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Warningln(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Warningln(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Error(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Error(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Errorf(format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Errorf(logger.thread, logger.isStd, logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Errorln(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Errorln(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Critical(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Critical(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Criticalf(format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Criticalf(logger.thread, logger.isStd, logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Criticalln(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Criticalln(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Fatal(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Fatal(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Fatalf(format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Fatalf(logger.thread, logger.isStd, logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Fatalln(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Fatalln(logger.thread, logger.isStd, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Print(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Print(logger.thread, logger.isStd, logger.GetShowStd(), logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Printf(format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Printf(logger.thread, logger.isStd, logger.GetShowStd(), logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Println(str ...interface{}) {
 | 
			
		||||
	logger.logcore.Println(logger.thread, logger.isStd, logger.GetShowStd(), logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Log(showLog bool, level int, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Log(logger.thread, logger.isStd, showLog, level, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Logf(showLog bool, level int, format string, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Logf(logger.thread, logger.isStd, showLog, level, logger.handlerFunc, format, str...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) Logln(showLog bool, level int, str ...interface{}) {
 | 
			
		||||
	logger.logcore.Logln(logger.thread, logger.isStd, showLog, level, logger.handlerFunc, str...)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										188
									
								
								vendor/b612.me/starlog/typed.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								vendor/b612.me/starlog/typed.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,188 @@
 | 
			
		||||
package starlog
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math/rand"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"b612.me/starlog/colorable"
 | 
			
		||||
	"b612.me/starmap"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	LvDebug = iota
 | 
			
		||||
	LvInfo
 | 
			
		||||
	LvNotice
 | 
			
		||||
	LvWarning
 | 
			
		||||
	LvError
 | 
			
		||||
	LvCritical
 | 
			
		||||
	LvPanic
 | 
			
		||||
	LvFatal
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	levels = map[int]string{
 | 
			
		||||
		LvDebug:    "DEBUG",
 | 
			
		||||
		LvInfo:     "INFO",
 | 
			
		||||
		LvNotice:   "NOTICE",
 | 
			
		||||
		LvWarning:  "WARNING",
 | 
			
		||||
		LvError:    "ERROR",
 | 
			
		||||
		LvCritical: "CRITICAL",
 | 
			
		||||
		LvPanic:    "PANIC",
 | 
			
		||||
		LvFatal:    "FATAL",
 | 
			
		||||
	}
 | 
			
		||||
	stacks        *starmap.StarStack
 | 
			
		||||
	stackStarted  bool = false
 | 
			
		||||
	stackStopChan chan int
 | 
			
		||||
	stackMu       sync.Mutex
 | 
			
		||||
	stdScreen     io.Writer = colorable.NewColorableStdout()
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type starlog struct {
 | 
			
		||||
	mu             *sync.Mutex
 | 
			
		||||
	output         io.Writer
 | 
			
		||||
	showFuncName   bool
 | 
			
		||||
	showThread     bool
 | 
			
		||||
	showLevel      bool
 | 
			
		||||
	showDeatilFile bool
 | 
			
		||||
	showColor      bool
 | 
			
		||||
	switching      bool
 | 
			
		||||
	showStd        bool
 | 
			
		||||
	onlyColorLevel bool
 | 
			
		||||
	stopWriter     bool
 | 
			
		||||
	id             string
 | 
			
		||||
 | 
			
		||||
	colorList map[int][]Attr
 | 
			
		||||
	colorMe   map[int]*Color
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type StarLogger struct {
 | 
			
		||||
	thread      string
 | 
			
		||||
	handlerFunc func([]Attr, string)
 | 
			
		||||
	logcore     *starlog
 | 
			
		||||
	isStd       bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type logTransfer struct {
 | 
			
		||||
	handlerFunc func([]Attr, string)
 | 
			
		||||
	colors      []Attr
 | 
			
		||||
	logStr      string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newLogCore(out io.Writer) *starlog {
 | 
			
		||||
	return &starlog{
 | 
			
		||||
		mu:             &sync.Mutex{},
 | 
			
		||||
		output:         out,
 | 
			
		||||
		showFuncName:   true,
 | 
			
		||||
		showThread:     true,
 | 
			
		||||
		showLevel:      true,
 | 
			
		||||
		showStd:        true,
 | 
			
		||||
		showDeatilFile: true,
 | 
			
		||||
		switching:      false,
 | 
			
		||||
		stopWriter:     false,
 | 
			
		||||
		showColor:      true,
 | 
			
		||||
		id:             generateId(),
 | 
			
		||||
		colorList: map[int][]Attr{
 | 
			
		||||
			LvDebug:    []Attr{FgWhite},
 | 
			
		||||
			LvInfo:     []Attr{FgGreen},
 | 
			
		||||
			LvNotice:   []Attr{FgBlue},
 | 
			
		||||
			LvWarning:  []Attr{FgYellow},
 | 
			
		||||
			LvError:    []Attr{FgMagenta},
 | 
			
		||||
			LvCritical: []Attr{FgRed, Bold},
 | 
			
		||||
			LvPanic:    []Attr{FgRed, Bold},
 | 
			
		||||
			LvFatal:    []Attr{FgRed},
 | 
			
		||||
		},
 | 
			
		||||
		colorMe: map[int]*Color{
 | 
			
		||||
			LvDebug:    NewColor([]Attr{FgWhite}...),
 | 
			
		||||
			LvInfo:     NewColor([]Attr{FgGreen}...),
 | 
			
		||||
			LvNotice:   NewColor([]Attr{FgBlue}...),
 | 
			
		||||
			LvWarning:  NewColor([]Attr{FgYellow}...),
 | 
			
		||||
			LvError:    NewColor([]Attr{FgMagenta}...),
 | 
			
		||||
			LvCritical: NewColor([]Attr{FgRed, Bold}...),
 | 
			
		||||
			LvPanic:    NewColor([]Attr{FgRed, Bold}...),
 | 
			
		||||
			LvFatal:    NewColor([]Attr{FgRed}...),
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewStarlog(out io.Writer) *StarLogger {
 | 
			
		||||
	return &StarLogger{
 | 
			
		||||
		handlerFunc: nil,
 | 
			
		||||
		thread:      "MAN",
 | 
			
		||||
		logcore:     newLogCore(out),
 | 
			
		||||
		isStd:       false,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (logger *StarLogger) NewFlag() *StarLogger {
 | 
			
		||||
	return &StarLogger{
 | 
			
		||||
		thread:      getRandomFlag(false),
 | 
			
		||||
		handlerFunc: logger.handlerFunc,
 | 
			
		||||
		logcore:     logger.logcore,
 | 
			
		||||
		isStd:       false,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (logger *StarLogger) SetNewRandomFlag() {
 | 
			
		||||
	logger.thread = getRandomFlag(false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getRandomFlag(isMain bool) string {
 | 
			
		||||
	rand.Seed(time.Now().UnixNano())
 | 
			
		||||
	if isMain {
 | 
			
		||||
		return "MAN"
 | 
			
		||||
	}
 | 
			
		||||
	flag := "MAN"
 | 
			
		||||
	for flag == "MAN" {
 | 
			
		||||
		flag = string([]byte{uint8(rand.Intn(26) + 65), uint8(rand.Intn(26) + 65), uint8(rand.Intn(26) + 65)})
 | 
			
		||||
	}
 | 
			
		||||
	return flag
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func generateId() string {
 | 
			
		||||
	rand.Seed(time.Now().UnixNano())
 | 
			
		||||
	return fmt.Sprintf("%dstar%db612%d", time.Now().UnixNano(), rand.Intn(1000000), rand.Intn(1000000))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StartStacks() {
 | 
			
		||||
	stackMu.Lock()
 | 
			
		||||
	if stackStarted {
 | 
			
		||||
		stackMu.Unlock()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	go func() {
 | 
			
		||||
		stackStarted = true
 | 
			
		||||
		stackMu.Unlock()
 | 
			
		||||
		defer func() {
 | 
			
		||||
			stackStarted = false
 | 
			
		||||
		}()
 | 
			
		||||
		for {
 | 
			
		||||
			select {
 | 
			
		||||
			case <-stackStopChan:
 | 
			
		||||
				return
 | 
			
		||||
			default:
 | 
			
		||||
			}
 | 
			
		||||
			poped := stacks.MustPop()
 | 
			
		||||
			if poped == nil {
 | 
			
		||||
				time.Sleep(time.Microsecond * 500)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			val := poped.(logTransfer)
 | 
			
		||||
			if val.handlerFunc != nil {
 | 
			
		||||
				val.handlerFunc(val.colors, val.logStr)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StopStacks() {
 | 
			
		||||
	if !stackStarted {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	stackStopChan <- 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Stop() {
 | 
			
		||||
	StopStacks()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										102
									
								
								vendor/b612.me/starmap/basicrw.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								vendor/b612.me/starmap/basicrw.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,102 @@
 | 
			
		||||
package starmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (stack *StarStackMem) Count() int {
 | 
			
		||||
	stack.kvPushmu.Lock()
 | 
			
		||||
	defer stack.kvPushmu.Unlock()
 | 
			
		||||
	return len(stack.kvStack)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (stack *StarStackMem) Push(val interface{}) error {
 | 
			
		||||
	stack.kvPushmu.Lock()
 | 
			
		||||
	defer stack.kvPushmu.Unlock()
 | 
			
		||||
	stack.kvStack = append(stack.kvStack, val)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (stack *StarStackMem) Pop() (interface{}, error) {
 | 
			
		||||
	stack.kvPushmu.Lock()
 | 
			
		||||
	defer stack.kvPushmu.Unlock()
 | 
			
		||||
	if len(stack.kvStack) == 0 {
 | 
			
		||||
		return nil, errors.New("Empty Stacks")
 | 
			
		||||
	}
 | 
			
		||||
	val := stack.kvStack[0]
 | 
			
		||||
	stack.kvStack = stack.kvStack[1:]
 | 
			
		||||
	return val, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (stack *StarStackMem) MustPop() interface{} {
 | 
			
		||||
	val, _ := stack.Pop()
 | 
			
		||||
	return val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Get(key interface{}) (interface{}, error) {
 | 
			
		||||
	return globalMap.Get(key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *StarMapKV) Get(key interface{}) (interface{}, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	m.mu.RLock()
 | 
			
		||||
	defer m.mu.RUnlock()
 | 
			
		||||
	data, ok := m.kvMap[key]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		err = os.ErrNotExist
 | 
			
		||||
	}
 | 
			
		||||
	return data, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *StarMapKV) MustGet(key interface{}) interface{} {
 | 
			
		||||
	result, _ := m.Get(key)
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
func MustGet(key interface{}) interface{} {
 | 
			
		||||
	return globalMap.MustGet(key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Store(key interface{}, value interface{}) error {
 | 
			
		||||
	return globalMap.Store(key, value)
 | 
			
		||||
}
 | 
			
		||||
func (m *StarMapKV) Store(key interface{}, value interface{}) error {
 | 
			
		||||
	m.mu.Lock()
 | 
			
		||||
	defer m.mu.Unlock()
 | 
			
		||||
	m.kvMap[key] = value
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Exists(key interface{}) bool {
 | 
			
		||||
	return globalMap.Exists(key)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *StarMapKV) Exists(key interface{}) bool {
 | 
			
		||||
	m.mu.RLock()
 | 
			
		||||
	defer m.mu.RUnlock()
 | 
			
		||||
	_, ok := m.kvMap[key]
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Delete(key interface{}) error {
 | 
			
		||||
	return globalMap.Delete(key)
 | 
			
		||||
}
 | 
			
		||||
func (m *StarMapKV) Delete(key interface{}) error {
 | 
			
		||||
	m.mu.Lock()
 | 
			
		||||
	defer m.mu.Unlock()
 | 
			
		||||
	delete(m.kvMap, key)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Range(run func(k interface{}, v interface{}) bool) error {
 | 
			
		||||
	return globalMap.Range(run)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (m *StarMapKV) Range(run func(k interface{}, v interface{}) bool) error {
 | 
			
		||||
	for k, v := range m.kvMap {
 | 
			
		||||
		if !run(k, v) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								vendor/b612.me/starmap/client_basicrw.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								vendor/b612.me/starmap/client_basicrw.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,96 @@
 | 
			
		||||
package starmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/notify"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) clientOnline() error {
 | 
			
		||||
	return kv.reconnect()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) MustGet(key string) interface{} {
 | 
			
		||||
	result, _ := kv.Get(key)
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) Get(key interface{}) (interface{}, error) {
 | 
			
		||||
	if err := kv.clientOnline(); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	keyCode, err := notify.ToMsgVal(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	data, err := kv.client.SendWait("get", keyCode, kv.readTimeout)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	rp, err := data.Value.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	reply := rp.(kvMsg)
 | 
			
		||||
	return reply.Value, reply.Err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) Store(key interface{}, value interface{}) error {
 | 
			
		||||
	if err := kv.clientOnline(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	encodeData, err := notify.ToMsgVal(kvMsg{
 | 
			
		||||
		Key:   key,
 | 
			
		||||
		Value: value,
 | 
			
		||||
		Err:   nil,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	data, err := kv.client.SendWait("store", encodeData, kv.readTimeout)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	rp, err := data.Value.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return rp.(kvMsg).Err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) Delete(key interface{}) error {
 | 
			
		||||
	if err := kv.clientOnline(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	keyCode, err := notify.ToMsgVal(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	data, err := kv.client.SendWait("delete", keyCode, kv.readTimeout)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	rp, err := data.Value.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return rp.(kvMsg).Err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) Exists(key interface{}) bool {
 | 
			
		||||
	if err := kv.clientOnline(); err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	keyCode, err := notify.ToMsgVal(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	data, err := kv.client.SendWait("exists", keyCode, kv.readTimeout)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	rp, err := data.Value.ToInterface()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	reply := rp.(kvMsg)
 | 
			
		||||
	return reply.Value.(bool)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										102
									
								
								vendor/b612.me/starmap/remote_define.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								vendor/b612.me/starmap/remote_define.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,102 @@
 | 
			
		||||
package starmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/gob"
 | 
			
		||||
	"os"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"b612.me/notify"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	notify.Register(kvMsg{})
 | 
			
		||||
	notify.Register(starMapErr{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type starMapErr struct {
 | 
			
		||||
	Err string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s starMapErr) Error() string {
 | 
			
		||||
	return s.Err
 | 
			
		||||
}
 | 
			
		||||
func newStarMapErr(err error) error {
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return starMapErr{Err: err.Error()}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type kvMsg struct {
 | 
			
		||||
	Key   interface{}
 | 
			
		||||
	Value interface{}
 | 
			
		||||
	Err   error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RemoteKv struct {
 | 
			
		||||
	server      notify.Server
 | 
			
		||||
	client      notify.Client
 | 
			
		||||
	kvmap       StarMapKV
 | 
			
		||||
	addr        string
 | 
			
		||||
	network     string
 | 
			
		||||
	readTimeout time.Duration
 | 
			
		||||
	timeout     time.Duration
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewServer(network, addr string) (*RemoteKv, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	kv := RemoteKv{
 | 
			
		||||
		server:  notify.NewServer(),
 | 
			
		||||
		kvmap:   NewStarMap(),
 | 
			
		||||
		addr:    addr,
 | 
			
		||||
		network: network,
 | 
			
		||||
	}
 | 
			
		||||
	err = kv.server.Listen(network, addr)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		kv.bind()
 | 
			
		||||
	}
 | 
			
		||||
	return &kv, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewClient(network, addr string, dialTimeout time.Duration) (*RemoteKv, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	kv := RemoteKv{
 | 
			
		||||
		client:      notify.NewClient(),
 | 
			
		||||
		kvmap:       NewStarMap(),
 | 
			
		||||
		addr:        addr,
 | 
			
		||||
		network:     network,
 | 
			
		||||
		timeout:     dialTimeout,
 | 
			
		||||
		readTimeout: time.Second * 5,
 | 
			
		||||
	}
 | 
			
		||||
	err = kv.client.ConnectTimeout(network, addr, dialTimeout)
 | 
			
		||||
	return &kv, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) Register(data interface{}) {
 | 
			
		||||
	gob.Register(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) RegisterAll(data []interface{}) {
 | 
			
		||||
	for _, v := range data {
 | 
			
		||||
		gob.Register(v)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) bind() {
 | 
			
		||||
	//for server
 | 
			
		||||
	kv.server.SetDefaultLink(kv.dispatch)
 | 
			
		||||
	//for client
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (kv *RemoteKv) reconnect() error {
 | 
			
		||||
	if kv.server != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if kv.client != nil {
 | 
			
		||||
		if kv.client.Status().Alive {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		return kv.client.ConnectTimeout(kv.network, kv.addr, kv.timeout)
 | 
			
		||||
	}
 | 
			
		||||
	return os.ErrInvalid
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/b612.me/starmap/server_basicrw.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								vendor/b612.me/starmap/server_basicrw.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
			
		||||
package starmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/notify"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (r *RemoteKv) dispatch(msg *notify.Message) {
 | 
			
		||||
	switch msg.Key {
 | 
			
		||||
	case "get":
 | 
			
		||||
		data, err := r.kvmap.Get(msg.Value.MustToInterface())
 | 
			
		||||
		msg.ReplyObj(kvMsg{
 | 
			
		||||
			Key:   msg.Value.MustToInterface(),
 | 
			
		||||
			Value: data,
 | 
			
		||||
			Err:   newStarMapErr(err),
 | 
			
		||||
		})
 | 
			
		||||
	case "delete":
 | 
			
		||||
		err := r.kvmap.Delete(msg.Value.MustToInterface())
 | 
			
		||||
		msg.ReplyObj(kvMsg{
 | 
			
		||||
			Key:   msg.Value.MustToInterface(),
 | 
			
		||||
			Value: nil,
 | 
			
		||||
			Err:   newStarMapErr(err),
 | 
			
		||||
		})
 | 
			
		||||
	case "exists":
 | 
			
		||||
		ext := r.kvmap.Exists(msg.Value.MustToInterface())
 | 
			
		||||
		msg.ReplyObj(kvMsg{
 | 
			
		||||
			Key:   msg.Value.MustToInterface(),
 | 
			
		||||
			Value: ext,
 | 
			
		||||
			Err:   newStarMapErr(nil),
 | 
			
		||||
		})
 | 
			
		||||
	case "store":
 | 
			
		||||
		ext := msg.Value.MustToInterface().(kvMsg)
 | 
			
		||||
		err := r.kvmap.Store(ext.Key, ext.Value)
 | 
			
		||||
		msg.ReplyObj(kvMsg{
 | 
			
		||||
			Key:   msg.Value.MustToInterface(),
 | 
			
		||||
			Value: nil,
 | 
			
		||||
			Err:   newStarMapErr(err),
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										199
									
								
								vendor/b612.me/starmap/stack.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								vendor/b612.me/starmap/stack.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,199 @@
 | 
			
		||||
package starmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type StarStack struct {
 | 
			
		||||
	datas   []interface{}
 | 
			
		||||
	pStart  uint64
 | 
			
		||||
	pEnd    uint64
 | 
			
		||||
	cap     uint64
 | 
			
		||||
	isClose atomic.Value
 | 
			
		||||
	rmu     sync.Mutex
 | 
			
		||||
	wmu     sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewStarStack(cap uint64) *StarStack {
 | 
			
		||||
	rtnBuffer := new(StarStack)
 | 
			
		||||
	rtnBuffer.cap = cap
 | 
			
		||||
	rtnBuffer.datas = make([]interface{}, cap)
 | 
			
		||||
	rtnBuffer.isClose.Store(false)
 | 
			
		||||
	return rtnBuffer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) init() {
 | 
			
		||||
	star.cap = 1024
 | 
			
		||||
	star.datas = make([]interface{}, star.cap)
 | 
			
		||||
	star.isClose.Store(false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) Free() uint64 {
 | 
			
		||||
	return star.cap - star.Len()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) Cap() uint64 {
 | 
			
		||||
	return star.cap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) Len() uint64 {
 | 
			
		||||
	if star.pEnd >= star.pStart {
 | 
			
		||||
		return star.pEnd - star.pStart
 | 
			
		||||
	}
 | 
			
		||||
	return star.pEnd - star.pStart + star.cap
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) PopNoWait() (interface{}, error) {
 | 
			
		||||
	if star.isClose.Load() == nil {
 | 
			
		||||
		star.init()
 | 
			
		||||
	}
 | 
			
		||||
	if star.isClose.Load().(bool) {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	if star.Len() == 0 {
 | 
			
		||||
		return 0, os.ErrNotExist
 | 
			
		||||
	}
 | 
			
		||||
	nowPtr := star.pStart
 | 
			
		||||
	nextPtr := star.pStart + 1
 | 
			
		||||
	if nextPtr >= star.cap {
 | 
			
		||||
		nextPtr = 0
 | 
			
		||||
	}
 | 
			
		||||
	data := star.datas[nowPtr]
 | 
			
		||||
	ok := atomic.CompareAndSwapUint64(&star.pStart, nowPtr, nextPtr)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return 0, os.ErrInvalid
 | 
			
		||||
	}
 | 
			
		||||
	return data, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) MustPop() interface{} {
 | 
			
		||||
	if star.isClose.Load() == nil {
 | 
			
		||||
		star.init()
 | 
			
		||||
	}
 | 
			
		||||
	data, err := star.Pop()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return data
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) Pop() (interface{}, error) {
 | 
			
		||||
	if star.isClose.Load() == nil {
 | 
			
		||||
		star.init()
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		if star.isClose.Load().(bool) {
 | 
			
		||||
			return 0, io.EOF
 | 
			
		||||
		}
 | 
			
		||||
		if star.Len() == 0 {
 | 
			
		||||
			return 0, os.ErrNotExist
 | 
			
		||||
		}
 | 
			
		||||
		nowPtr := star.pStart
 | 
			
		||||
		nextPtr := star.pStart + 1
 | 
			
		||||
		if nextPtr >= star.cap {
 | 
			
		||||
			nextPtr = 0
 | 
			
		||||
		}
 | 
			
		||||
		data := star.datas[nowPtr]
 | 
			
		||||
		ok := atomic.CompareAndSwapUint64(&star.pStart, nowPtr, nextPtr)
 | 
			
		||||
		if !ok {
 | 
			
		||||
			time.Sleep(time.Microsecond)
 | 
			
		||||
			runtime.Gosched()
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		return data, nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) Push(data interface{}) error {
 | 
			
		||||
	if star.isClose.Load() == nil {
 | 
			
		||||
		star.init()
 | 
			
		||||
	}
 | 
			
		||||
	if star.isClose.Load().(bool) {
 | 
			
		||||
		return io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	nowPtr := star.pEnd
 | 
			
		||||
	kariEnd := nowPtr + 1
 | 
			
		||||
	if kariEnd == star.cap {
 | 
			
		||||
		kariEnd = 0
 | 
			
		||||
	}
 | 
			
		||||
	if kariEnd == atomic.LoadUint64(&star.pStart) {
 | 
			
		||||
		for {
 | 
			
		||||
			time.Sleep(time.Microsecond)
 | 
			
		||||
			runtime.Gosched()
 | 
			
		||||
			if kariEnd != atomic.LoadUint64(&star.pStart) {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	star.datas[nowPtr] = data
 | 
			
		||||
	if ok := atomic.CompareAndSwapUint64(&star.pEnd, nowPtr, kariEnd); !ok {
 | 
			
		||||
		return os.ErrInvalid
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) Close() error {
 | 
			
		||||
	if star.isClose.Load() == nil {
 | 
			
		||||
		star.init()
 | 
			
		||||
	}
 | 
			
		||||
	star.isClose.Store(true)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func (star *StarStack) Read(buf []interface{}) (int, error) {
 | 
			
		||||
	if star.isClose.Load() == nil {
 | 
			
		||||
		star.init()
 | 
			
		||||
	}
 | 
			
		||||
	if star.isClose.Load().(bool) {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	if buf == nil {
 | 
			
		||||
		return 0, errors.New("buffer is nil")
 | 
			
		||||
	}
 | 
			
		||||
	star.rmu.Lock()
 | 
			
		||||
	defer star.rmu.Unlock()
 | 
			
		||||
	var sum int = 0
 | 
			
		||||
	for i := 0; i < len(buf); i++ {
 | 
			
		||||
		data, err := star.PopNoWait()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err == io.EOF {
 | 
			
		||||
				return sum, err
 | 
			
		||||
			}
 | 
			
		||||
			if err == os.ErrNotExist {
 | 
			
		||||
				i--
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			return sum, nil
 | 
			
		||||
		}
 | 
			
		||||
		buf[i] = data
 | 
			
		||||
		sum++
 | 
			
		||||
	}
 | 
			
		||||
	return sum, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (star *StarStack) Write(bts []byte) (int, error) {
 | 
			
		||||
	if star.isClose.Load() == nil {
 | 
			
		||||
		star.init()
 | 
			
		||||
	}
 | 
			
		||||
	if bts == nil || star.isClose.Load().(bool) {
 | 
			
		||||
		return 0, io.EOF
 | 
			
		||||
	}
 | 
			
		||||
	star.wmu.Lock()
 | 
			
		||||
	defer star.wmu.Unlock()
 | 
			
		||||
	var sum = 0
 | 
			
		||||
	for i := 0; i < len(bts); i++ {
 | 
			
		||||
		err := star.Push(bts[i])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			fmt.Println("Write bts err:", err)
 | 
			
		||||
			return sum, err
 | 
			
		||||
		}
 | 
			
		||||
		sum++
 | 
			
		||||
	}
 | 
			
		||||
	return sum, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										25
									
								
								vendor/b612.me/starmap/starmap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								vendor/b612.me/starmap/starmap.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
package starmap
 | 
			
		||||
 | 
			
		||||
import "sync"
 | 
			
		||||
 | 
			
		||||
var globalMap StarMapKV
 | 
			
		||||
 | 
			
		||||
type StarMapKV struct {
 | 
			
		||||
	kvMap map[interface{}]interface{}
 | 
			
		||||
	mu    sync.RWMutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type StarStackMem struct {
 | 
			
		||||
	kvPushmu sync.RWMutex
 | 
			
		||||
	kvStack  []interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	globalMap = NewStarMap()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewStarMap() StarMapKV {
 | 
			
		||||
	var mp StarMapKV
 | 
			
		||||
	mp.kvMap = make(map[interface{}]interface{})
 | 
			
		||||
	return mp
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										55
									
								
								vendor/b612.me/starmap/sync.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								vendor/b612.me/starmap/sync.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
package starmap
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type WaitGroup struct {
 | 
			
		||||
	wg       *sync.WaitGroup
 | 
			
		||||
	maxCount uint32
 | 
			
		||||
	allCount uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewWaitGroup(maxCount int) WaitGroup {
 | 
			
		||||
	return WaitGroup{wg: &sync.WaitGroup{}, maxCount: uint32(maxCount)}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) Add(delta int) {
 | 
			
		||||
	var Udelta uint32
 | 
			
		||||
	if delta < 0 {
 | 
			
		||||
		Udelta = uint32(-delta - 1)
 | 
			
		||||
	} else {
 | 
			
		||||
		Udelta = uint32(delta)
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		allC := atomic.LoadUint32(&swg.allCount)
 | 
			
		||||
		if atomic.LoadUint32(&swg.maxCount) == 0 || atomic.LoadUint32(&swg.maxCount) >= allC+uint32(delta) {
 | 
			
		||||
			if delta < 0 {
 | 
			
		||||
				atomic.AddUint32(&swg.allCount, ^uint32(Udelta))
 | 
			
		||||
			} else {
 | 
			
		||||
				atomic.AddUint32(&swg.allCount, uint32(Udelta))
 | 
			
		||||
			}
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		time.Sleep(time.Microsecond)
 | 
			
		||||
	}
 | 
			
		||||
	swg.wg.Add(delta)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) Done() {
 | 
			
		||||
	swg.Add(-1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) Wait() {
 | 
			
		||||
	swg.wg.Wait()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) GetMaxWaitNum() int {
 | 
			
		||||
	return int(atomic.LoadUint32(&swg.maxCount))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (swg *WaitGroup) SetMaxWaitNum(num int) {
 | 
			
		||||
	atomic.AddUint32(&swg.maxCount, uint32(num))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										435
									
								
								vendor/b612.me/starnet/curl.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										435
									
								
								vendor/b612.me/starnet/curl.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,435 @@
 | 
			
		||||
package starnet
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"b612.me/stario"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	HEADER_FORM_URLENCODE = `application/x-www-form-urlencoded`
 | 
			
		||||
	HEADER_FORM_DATA      = `multipart/form-data`
 | 
			
		||||
	HEADER_JSON           = `application/json`
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type RequestFile struct {
 | 
			
		||||
	UploadFile string
 | 
			
		||||
	UploadForm map[string]string
 | 
			
		||||
	UploadName string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Request struct {
 | 
			
		||||
	Url               string
 | 
			
		||||
	Method            string
 | 
			
		||||
	RecvData          []byte
 | 
			
		||||
	RecvContentLength int64
 | 
			
		||||
	RecvIo            io.Writer
 | 
			
		||||
	RespHeader        http.Header
 | 
			
		||||
	RespCookies       []*http.Cookie
 | 
			
		||||
	RespHttpCode      int
 | 
			
		||||
	Location          *url.URL
 | 
			
		||||
	CircleBuffer      *stario.StarBuffer
 | 
			
		||||
	respReader        io.ReadCloser
 | 
			
		||||
	RequestOpts
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RequestOpts struct {
 | 
			
		||||
	RequestFile
 | 
			
		||||
	PostBuffer      io.Reader
 | 
			
		||||
	Process         func(float64)
 | 
			
		||||
	Proxy           string
 | 
			
		||||
	Timeout         time.Duration
 | 
			
		||||
	DialTimeout     time.Duration
 | 
			
		||||
	ReqHeader       http.Header
 | 
			
		||||
	ReqCookies      []*http.Cookie
 | 
			
		||||
	WriteRecvData   bool
 | 
			
		||||
	SkipTLSVerify   bool
 | 
			
		||||
	CustomTransport *http.Transport
 | 
			
		||||
	Queries         map[string]string
 | 
			
		||||
	DisableRedirect bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type RequestOpt func(opt *RequestOpts)
 | 
			
		||||
 | 
			
		||||
func WithDialTimeout(timeout time.Duration) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.DialTimeout = timeout
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithTimeout(timeout time.Duration) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.Timeout = timeout
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithHeader(key, val string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.ReqHeader.Set(key, val)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithHeaderMap(header map[string]string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		for key, val := range header {
 | 
			
		||||
			opt.ReqHeader.Set(key, val)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithHeaderAdd(key, val string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.ReqHeader.Add(key, val)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithReader(r io.Reader) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.PostBuffer = r
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithFetchRespBody(fetch bool) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.WriteRecvData = fetch
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithCookies(ck []*http.Cookie) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.ReqCookies = ck
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithCookie(key, val, path string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.ReqCookies = append(opt.ReqCookies, &http.Cookie{Name: key, Value: val, Path: path})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithCookieMap(header map[string]string, path string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		for key, val := range header {
 | 
			
		||||
			opt.ReqCookies = append(opt.ReqCookies, &http.Cookie{Name: key, Value: val, Path: path})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithQueries(queries map[string]string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.Queries = queries
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithProxy(proxy string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.Proxy = proxy
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithProcess(fn func(float64)) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.Process = fn
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithContentType(ct string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.ReqHeader.Set("Content-Type", ct)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithUserAgent(ua string) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.ReqHeader.Set("User-Agent", ua)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithCustomTransport(hs *http.Transport) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.CustomTransport = hs
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithSkipTLSVerify(skip bool) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.SkipTLSVerify = skip
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WithDisableRedirect(disable bool) RequestOpt {
 | 
			
		||||
	return func(opt *RequestOpts) {
 | 
			
		||||
		opt.DisableRedirect = disable
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewRequests(url string, rawdata []byte, method string, opts ...RequestOpt) Request {
 | 
			
		||||
	req := Request{
 | 
			
		||||
		RequestOpts: RequestOpts{
 | 
			
		||||
			Timeout:       30 * time.Second,
 | 
			
		||||
			DialTimeout:   15 * time.Second,
 | 
			
		||||
			WriteRecvData: true,
 | 
			
		||||
		},
 | 
			
		||||
		Url:    url,
 | 
			
		||||
		Method: method,
 | 
			
		||||
	}
 | 
			
		||||
	if rawdata != nil {
 | 
			
		||||
		req.PostBuffer = bytes.NewBuffer(rawdata)
 | 
			
		||||
	}
 | 
			
		||||
	req.ReqHeader = make(http.Header)
 | 
			
		||||
	if strings.ToUpper(method) == "POST" {
 | 
			
		||||
		req.ReqHeader.Set("Content-Type", HEADER_FORM_URLENCODE)
 | 
			
		||||
	}
 | 
			
		||||
	req.ReqHeader.Set("User-Agent", "B612 / 1.1.0")
 | 
			
		||||
	for _, v := range opts {
 | 
			
		||||
		v(&req.RequestOpts)
 | 
			
		||||
	}
 | 
			
		||||
	if req.CustomTransport == nil {
 | 
			
		||||
		req.CustomTransport = &http.Transport{}
 | 
			
		||||
	}
 | 
			
		||||
	if req.SkipTLSVerify {
 | 
			
		||||
		if req.CustomTransport.TLSClientConfig == nil {
 | 
			
		||||
			req.CustomTransport.TLSClientConfig = &tls.Config{}
 | 
			
		||||
		}
 | 
			
		||||
		req.CustomTransport.TLSClientConfig.InsecureSkipVerify = true
 | 
			
		||||
	}
 | 
			
		||||
	req.CustomTransport.DialContext = func(ctx context.Context, netw, addr string) (net.Conn, error) {
 | 
			
		||||
		c, err := net.DialTimeout(netw, addr, req.DialTimeout)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		if req.Timeout != 0 {
 | 
			
		||||
			c.SetDeadline(time.Now().Add(req.Timeout))
 | 
			
		||||
		}
 | 
			
		||||
		return c, nil
 | 
			
		||||
	}
 | 
			
		||||
	return req
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (curl *Request) ResetReqHeader() {
 | 
			
		||||
	curl.ReqHeader = make(http.Header)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (curl *Request) ResetReqCookies() {
 | 
			
		||||
	curl.ReqCookies = []*http.Cookie{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (curl *Request) AddSimpleCookie(key, value string) {
 | 
			
		||||
	curl.ReqCookies = append(curl.ReqCookies, &http.Cookie{Name: key, Value: value, Path: "/"})
 | 
			
		||||
}
 | 
			
		||||
func (curl *Request) AddCookie(key, value, path string) {
 | 
			
		||||
	curl.ReqCookies = append(curl.ReqCookies, &http.Cookie{Name: key, Value: value, Path: path})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func randomBoundary() string {
 | 
			
		||||
	var buf [30]byte
 | 
			
		||||
	_, err := io.ReadFull(rand.Reader, buf[:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	return fmt.Sprintf("%x", buf[:])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Curl(curl Request) (resps Request, err error) {
 | 
			
		||||
	var fpsrc *os.File
 | 
			
		||||
	if curl.RequestFile.UploadFile != "" {
 | 
			
		||||
		fpsrc, err = os.Open(curl.UploadFile)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		defer fpsrc.Close()
 | 
			
		||||
		boundary := randomBoundary()
 | 
			
		||||
		boundarybytes := []byte("\r\n--" + boundary + "\r\n")
 | 
			
		||||
		endbytes := []byte("\r\n--" + boundary + "--\r\n")
 | 
			
		||||
		fpstat, _ := fpsrc.Stat()
 | 
			
		||||
		filebig := float64(fpstat.Size())
 | 
			
		||||
		sum, n := 0, 0
 | 
			
		||||
		fpdst := stario.NewStarBuffer(1048576)
 | 
			
		||||
		if curl.UploadForm != nil {
 | 
			
		||||
			for k, v := range curl.UploadForm {
 | 
			
		||||
				header := fmt.Sprintf("Content-Disposition: form-data; name=\"%s\";\r\nContent-Type: x-www-form-urlencoded \r\n\r\n", k)
 | 
			
		||||
				fpdst.Write(boundarybytes)
 | 
			
		||||
				fpdst.Write([]byte(header))
 | 
			
		||||
				fpdst.Write([]byte(v))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		header := fmt.Sprintf("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: application/octet-stream\r\n\r\n", curl.UploadName, fpstat.Name())
 | 
			
		||||
		fpdst.Write(boundarybytes)
 | 
			
		||||
		fpdst.Write([]byte(header))
 | 
			
		||||
		go func() {
 | 
			
		||||
			for {
 | 
			
		||||
				bufs := make([]byte, 393213)
 | 
			
		||||
				n, err = fpsrc.Read(bufs)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					if err == io.EOF {
 | 
			
		||||
						if n != 0 {
 | 
			
		||||
							fpdst.Write(bufs[0:n])
 | 
			
		||||
							if curl.Process != nil {
 | 
			
		||||
								go curl.Process(float64(sum+n) / filebig * 100)
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				sum += n
 | 
			
		||||
				if curl.Process != nil {
 | 
			
		||||
					go curl.Process(float64(sum+n) / filebig * 100)
 | 
			
		||||
				}
 | 
			
		||||
				fpdst.Write(bufs[0:n])
 | 
			
		||||
			}
 | 
			
		||||
			fpdst.Write(endbytes)
 | 
			
		||||
			fpdst.Write(nil)
 | 
			
		||||
		}()
 | 
			
		||||
		curl.CircleBuffer = fpdst
 | 
			
		||||
		curl.ReqHeader.Set("Content-Type", "multipart/form-data;boundary="+boundary)
 | 
			
		||||
	}
 | 
			
		||||
	resp, err := netcurl(curl)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Request{}, err
 | 
			
		||||
	}
 | 
			
		||||
	curl.Location, _ = resp.Location()
 | 
			
		||||
	curl.RespHttpCode = resp.StatusCode
 | 
			
		||||
	curl.RespHeader = resp.Header
 | 
			
		||||
	curl.RespCookies = resp.Cookies()
 | 
			
		||||
	curl.RecvContentLength = resp.ContentLength
 | 
			
		||||
	readFunc := func(reader io.ReadCloser, writer io.Writer) error {
 | 
			
		||||
		lengthall := resp.ContentLength
 | 
			
		||||
		defer reader.Close()
 | 
			
		||||
		var lengthsum int
 | 
			
		||||
		buf := make([]byte, 65535)
 | 
			
		||||
		for {
 | 
			
		||||
			n, err := reader.Read(buf)
 | 
			
		||||
			if n != 0 {
 | 
			
		||||
				_, err := writer.Write(buf[:n])
 | 
			
		||||
				lengthsum += n
 | 
			
		||||
				if curl.Process != nil {
 | 
			
		||||
					go curl.Process(float64(lengthsum) / float64(lengthall) * 100.00)
 | 
			
		||||
				}
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if err != nil && err != io.EOF {
 | 
			
		||||
				return err
 | 
			
		||||
			} else if err == io.EOF {
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if curl.WriteRecvData {
 | 
			
		||||
		buf := bytes.NewBuffer([]byte{})
 | 
			
		||||
		err = readFunc(resp.Body, buf)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		curl.RecvData = buf.Bytes()
 | 
			
		||||
	} else {
 | 
			
		||||
		curl.respReader = resp.Body
 | 
			
		||||
	}
 | 
			
		||||
	if curl.RecvIo != nil {
 | 
			
		||||
		if curl.WriteRecvData {
 | 
			
		||||
			_, err = curl.RecvIo.Write(curl.RecvData)
 | 
			
		||||
		} else {
 | 
			
		||||
			err = readFunc(resp.Body, curl.RecvIo)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return curl, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RespBodyReader Only works when WriteRecvData set to false
 | 
			
		||||
func (curl *Request) RespBodyReader() io.ReadCloser {
 | 
			
		||||
	return curl.respReader
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func netcurl(curl Request) (*http.Response, error) {
 | 
			
		||||
	var req *http.Request
 | 
			
		||||
	var err error
 | 
			
		||||
	if curl.Method == "" {
 | 
			
		||||
		return nil, errors.New("Error Method Not Entered")
 | 
			
		||||
	}
 | 
			
		||||
	if curl.PostBuffer != nil {
 | 
			
		||||
		req, err = http.NewRequest(curl.Method, curl.Url, curl.PostBuffer)
 | 
			
		||||
	} else if curl.CircleBuffer != nil && curl.CircleBuffer.Len() > 0 {
 | 
			
		||||
		req, err = http.NewRequest(curl.Method, curl.Url, curl.CircleBuffer)
 | 
			
		||||
	} else {
 | 
			
		||||
		req, err = http.NewRequest(curl.Method, curl.Url, nil)
 | 
			
		||||
	}
 | 
			
		||||
	if curl.Queries != nil {
 | 
			
		||||
		sid := req.URL.Query()
 | 
			
		||||
		for k, v := range curl.Queries {
 | 
			
		||||
			sid.Add(k, v)
 | 
			
		||||
		}
 | 
			
		||||
		req.URL.RawQuery = sid.Encode()
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	req.Header = curl.ReqHeader
 | 
			
		||||
	if len(curl.ReqCookies) != 0 {
 | 
			
		||||
		for _, v := range curl.ReqCookies {
 | 
			
		||||
			req.AddCookie(v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if curl.Proxy != "" {
 | 
			
		||||
		purl, err := url.Parse(curl.Proxy)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		curl.CustomTransport.Proxy = http.ProxyURL(purl)
 | 
			
		||||
	}
 | 
			
		||||
	client := &http.Client{
 | 
			
		||||
		Transport: curl.CustomTransport,
 | 
			
		||||
	}
 | 
			
		||||
	if curl.DisableRedirect {
 | 
			
		||||
		client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
 | 
			
		||||
			return http.ErrUseLastResponse
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	resp, err := client.Do(req)
 | 
			
		||||
	return resp, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func UrlEncodeRaw(str string) string {
 | 
			
		||||
	strs := strings.Replace(url.QueryEscape(str), "+", "%20", -1)
 | 
			
		||||
	return strs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func UrlEncode(str string) string {
 | 
			
		||||
	return url.QueryEscape(str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func UrlDecode(str string) (string, error) {
 | 
			
		||||
	return url.QueryUnescape(str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BuildQuery(queryData map[string]string) string {
 | 
			
		||||
	query := url.Values{}
 | 
			
		||||
	for k, v := range queryData {
 | 
			
		||||
		query.Add(k, v)
 | 
			
		||||
	}
 | 
			
		||||
	return query.Encode()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BuildPostForm(queryMap map[string]string) []byte {
 | 
			
		||||
	query := url.Values{}
 | 
			
		||||
	for k, v := range queryMap {
 | 
			
		||||
		query.Add(k, v)
 | 
			
		||||
	}
 | 
			
		||||
	return []byte(query.Encode())
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										97
									
								
								vendor/b612.me/starnet/ping.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								vendor/b612.me/starnet/ping.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,97 @@
 | 
			
		||||
package starnet
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ICMP struct {
 | 
			
		||||
	Type        uint8
 | 
			
		||||
	Code        uint8
 | 
			
		||||
	CheckSum    uint16
 | 
			
		||||
	Identifier  uint16
 | 
			
		||||
	SequenceNum uint16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getICMP(seq uint16) ICMP {
 | 
			
		||||
	icmp := ICMP{
 | 
			
		||||
		Type:        8,
 | 
			
		||||
		Code:        0,
 | 
			
		||||
		CheckSum:    0,
 | 
			
		||||
		Identifier:  0,
 | 
			
		||||
		SequenceNum: seq,
 | 
			
		||||
	}
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	binary.Write(&buffer, binary.BigEndian, icmp)
 | 
			
		||||
	icmp.CheckSum = checkSum(buffer.Bytes())
 | 
			
		||||
	buffer.Reset()
 | 
			
		||||
 | 
			
		||||
	return icmp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sendICMPRequest(icmp ICMP, destAddr *net.IPAddr, timeout time.Duration) (PingResult, error) {
 | 
			
		||||
	var res PingResult
 | 
			
		||||
	conn, err := net.DialIP("ip:icmp", nil, destAddr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
	defer conn.Close()
 | 
			
		||||
	var buffer bytes.Buffer
 | 
			
		||||
	binary.Write(&buffer, binary.BigEndian, icmp)
 | 
			
		||||
 | 
			
		||||
	if _, err := conn.Write(buffer.Bytes()); err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tStart := time.Now()
 | 
			
		||||
 | 
			
		||||
	conn.SetReadDeadline((time.Now().Add(timeout)))
 | 
			
		||||
 | 
			
		||||
	recv := make([]byte, 1024)
 | 
			
		||||
	res.RecvCount, err = conn.Read(recv)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tEnd := time.Now()
 | 
			
		||||
	res.Duration = tEnd.Sub(tStart)
 | 
			
		||||
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkSum(data []byte) uint16 {
 | 
			
		||||
	var (
 | 
			
		||||
		sum    uint32
 | 
			
		||||
		length int = len(data)
 | 
			
		||||
		index  int
 | 
			
		||||
	)
 | 
			
		||||
	for length > 1 {
 | 
			
		||||
		sum += uint32(data[index])<<8 + uint32(data[index+1])
 | 
			
		||||
		index += 2
 | 
			
		||||
		length -= 2
 | 
			
		||||
	}
 | 
			
		||||
	if length > 0 {
 | 
			
		||||
		sum += uint32(data[index])
 | 
			
		||||
	}
 | 
			
		||||
	sum += (sum >> 16)
 | 
			
		||||
 | 
			
		||||
	return uint16(^sum)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type PingResult struct {
 | 
			
		||||
	Duration  time.Duration
 | 
			
		||||
	RecvCount int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Ping(ip string, seq int, timeout time.Duration) (PingResult, error) {
 | 
			
		||||
	var res PingResult
 | 
			
		||||
	ipAddr, err := net.ResolveIPAddr("ip", ip)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
	icmp := getICMP(uint16(seq))
 | 
			
		||||
	return sendICMPRequest(icmp, ipAddr, timeout)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										317
									
								
								vendor/b612.me/starnet/que.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								vendor/b612.me/starnet/que.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,317 @@
 | 
			
		||||
package starnet
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"context"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// 识别头
 | 
			
		||||
var header = []byte{11, 27, 19, 96, 12, 25, 02, 20}
 | 
			
		||||
 | 
			
		||||
// MsgQueue 为基本的信息单位
 | 
			
		||||
type MsgQueue struct {
 | 
			
		||||
	ID   uint16
 | 
			
		||||
	Msg  []byte
 | 
			
		||||
	Conn interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StarQueue 为流数据中的消息队列分发
 | 
			
		||||
type StarQueue struct {
 | 
			
		||||
	count      int64
 | 
			
		||||
	Encode     bool
 | 
			
		||||
	Reserve    uint16
 | 
			
		||||
	Msgid      uint16
 | 
			
		||||
	MsgPool    chan MsgQueue
 | 
			
		||||
	UnFinMsg   sync.Map
 | 
			
		||||
	LastID     int //= -1
 | 
			
		||||
	ctx        context.Context
 | 
			
		||||
	cancel     context.CancelFunc
 | 
			
		||||
	duration   time.Duration
 | 
			
		||||
	EncodeFunc func([]byte) []byte
 | 
			
		||||
	DecodeFunc func([]byte) []byte
 | 
			
		||||
	//restoreMu  sync.Mutex
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewQueueCtx(ctx context.Context, count int64) *StarQueue {
 | 
			
		||||
	var que StarQueue
 | 
			
		||||
	que.Encode = false
 | 
			
		||||
	que.count = count
 | 
			
		||||
	que.MsgPool = make(chan MsgQueue, count)
 | 
			
		||||
	if ctx == nil {
 | 
			
		||||
		que.ctx, que.cancel = context.WithCancel(context.Background())
 | 
			
		||||
	} else {
 | 
			
		||||
		que.ctx, que.cancel = context.WithCancel(ctx)
 | 
			
		||||
	}
 | 
			
		||||
	que.duration = 0
 | 
			
		||||
	return &que
 | 
			
		||||
}
 | 
			
		||||
func NewQueueWithCount(count int64) *StarQueue {
 | 
			
		||||
	return NewQueueCtx(nil, count)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewQueue 建立一个新消息队列
 | 
			
		||||
func NewQueue() *StarQueue {
 | 
			
		||||
	return NewQueueWithCount(32)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Uint32ToByte 4位uint32转byte
 | 
			
		||||
func Uint32ToByte(src uint32) []byte {
 | 
			
		||||
	res := make([]byte, 4)
 | 
			
		||||
	res[3] = uint8(src)
 | 
			
		||||
	res[2] = uint8(src >> 8)
 | 
			
		||||
	res[1] = uint8(src >> 16)
 | 
			
		||||
	res[0] = uint8(src >> 24)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ByteToUint32 byte转4位uint32
 | 
			
		||||
func ByteToUint32(src []byte) uint32 {
 | 
			
		||||
	var res uint32
 | 
			
		||||
	buffer := bytes.NewBuffer(src)
 | 
			
		||||
	binary.Read(buffer, binary.BigEndian, &res)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Uint16ToByte 2位uint16转byte
 | 
			
		||||
func Uint16ToByte(src uint16) []byte {
 | 
			
		||||
	res := make([]byte, 2)
 | 
			
		||||
	res[1] = uint8(src)
 | 
			
		||||
	res[0] = uint8(src >> 8)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ByteToUint16 用于byte转uint16
 | 
			
		||||
func ByteToUint16(src []byte) uint16 {
 | 
			
		||||
	var res uint16
 | 
			
		||||
	buffer := bytes.NewBuffer(src)
 | 
			
		||||
	binary.Read(buffer, binary.BigEndian, &res)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildMessage 生成编码后的信息用于发送
 | 
			
		||||
func (que *StarQueue) BuildMessage(src []byte) []byte {
 | 
			
		||||
	var buff bytes.Buffer
 | 
			
		||||
	que.Msgid++
 | 
			
		||||
	if que.Encode {
 | 
			
		||||
		src = que.EncodeFunc(src)
 | 
			
		||||
	}
 | 
			
		||||
	length := uint32(len(src))
 | 
			
		||||
	buff.Write(header)
 | 
			
		||||
	buff.Write(Uint32ToByte(length))
 | 
			
		||||
	buff.Write(Uint16ToByte(que.Msgid))
 | 
			
		||||
	buff.Write(src)
 | 
			
		||||
	return buff.Bytes()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BuildHeader 生成编码后的Header用于发送
 | 
			
		||||
func (que *StarQueue) BuildHeader(length uint32) []byte {
 | 
			
		||||
	var buff bytes.Buffer
 | 
			
		||||
	que.Msgid++
 | 
			
		||||
	buff.Write(header)
 | 
			
		||||
	buff.Write(Uint32ToByte(length))
 | 
			
		||||
	buff.Write(Uint16ToByte(que.Msgid))
 | 
			
		||||
	return buff.Bytes()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type unFinMsg struct {
 | 
			
		||||
	ID         uint16
 | 
			
		||||
	LengthRecv uint32
 | 
			
		||||
	// HeaderMsg 信息头,应当为14位:8位识别码+4位长度码+2位id
 | 
			
		||||
	HeaderMsg []byte
 | 
			
		||||
	RecvMsg   []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (que *StarQueue) push2list(msg MsgQueue) {
 | 
			
		||||
	que.MsgPool <- msg
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ParseMessage 用于解析收到的msg信息
 | 
			
		||||
func (que *StarQueue) ParseMessage(msg []byte, conn interface{}) error {
 | 
			
		||||
	return que.parseMessage(msg, conn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseMessage 用于解析收到的msg信息
 | 
			
		||||
func (que *StarQueue) parseMessage(msg []byte, conn interface{}) error {
 | 
			
		||||
	tmp, ok := que.UnFinMsg.Load(conn)
 | 
			
		||||
	if ok { //存在未完成的信息
 | 
			
		||||
		lastMsg := tmp.(*unFinMsg)
 | 
			
		||||
		headerLen := len(lastMsg.HeaderMsg)
 | 
			
		||||
		if headerLen < 14 { //未完成头标题
 | 
			
		||||
			//传输的数据不能填充header头
 | 
			
		||||
			if len(msg) < 14-headerLen {
 | 
			
		||||
				//加入header头并退出
 | 
			
		||||
				lastMsg.HeaderMsg = bytesMerge(lastMsg.HeaderMsg, msg)
 | 
			
		||||
				que.UnFinMsg.Store(conn, lastMsg)
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
			//获取14字节完整的header
 | 
			
		||||
			header := msg[0 : 14-headerLen]
 | 
			
		||||
			lastMsg.HeaderMsg = bytesMerge(lastMsg.HeaderMsg, header)
 | 
			
		||||
			//检查收到的header是否为认证header
 | 
			
		||||
			//若不是,丢弃并重新来过
 | 
			
		||||
			if !checkHeader(lastMsg.HeaderMsg[0:8]) {
 | 
			
		||||
				que.UnFinMsg.Delete(conn)
 | 
			
		||||
				if len(msg) == 0 {
 | 
			
		||||
					return nil
 | 
			
		||||
				}
 | 
			
		||||
				return que.parseMessage(msg, conn)
 | 
			
		||||
			}
 | 
			
		||||
			//获得本数据包长度
 | 
			
		||||
			lastMsg.LengthRecv = ByteToUint32(lastMsg.HeaderMsg[8:12])
 | 
			
		||||
			//获得本数据包ID
 | 
			
		||||
			lastMsg.ID = ByteToUint16(lastMsg.HeaderMsg[12:14])
 | 
			
		||||
			//存入列表
 | 
			
		||||
			que.UnFinMsg.Store(conn, lastMsg)
 | 
			
		||||
			msg = msg[14-headerLen:]
 | 
			
		||||
			if uint32(len(msg)) < lastMsg.LengthRecv {
 | 
			
		||||
				lastMsg.RecvMsg = msg
 | 
			
		||||
				que.UnFinMsg.Store(conn, lastMsg)
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
			if uint32(len(msg)) >= lastMsg.LengthRecv {
 | 
			
		||||
				lastMsg.RecvMsg = msg[0:lastMsg.LengthRecv]
 | 
			
		||||
				if que.Encode {
 | 
			
		||||
					lastMsg.RecvMsg = que.DecodeFunc(lastMsg.RecvMsg)
 | 
			
		||||
				}
 | 
			
		||||
				msg = msg[lastMsg.LengthRecv:]
 | 
			
		||||
				storeMsg := MsgQueue{
 | 
			
		||||
					ID:   lastMsg.ID,
 | 
			
		||||
					Msg:  lastMsg.RecvMsg,
 | 
			
		||||
					Conn: conn,
 | 
			
		||||
				}
 | 
			
		||||
				//que.restoreMu.Lock()
 | 
			
		||||
				que.push2list(storeMsg)
 | 
			
		||||
				//que.restoreMu.Unlock()
 | 
			
		||||
				que.UnFinMsg.Delete(conn)
 | 
			
		||||
				return que.parseMessage(msg, conn)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			lastID := int(lastMsg.LengthRecv) - len(lastMsg.RecvMsg)
 | 
			
		||||
			if lastID < 0 {
 | 
			
		||||
				que.UnFinMsg.Delete(conn)
 | 
			
		||||
				return que.parseMessage(msg, conn)
 | 
			
		||||
			}
 | 
			
		||||
			if len(msg) >= lastID {
 | 
			
		||||
				lastMsg.RecvMsg = bytesMerge(lastMsg.RecvMsg, msg[0:lastID])
 | 
			
		||||
				if que.Encode {
 | 
			
		||||
					lastMsg.RecvMsg = que.DecodeFunc(lastMsg.RecvMsg)
 | 
			
		||||
				}
 | 
			
		||||
				storeMsg := MsgQueue{
 | 
			
		||||
					ID:   lastMsg.ID,
 | 
			
		||||
					Msg:  lastMsg.RecvMsg,
 | 
			
		||||
					Conn: conn,
 | 
			
		||||
				}
 | 
			
		||||
				que.push2list(storeMsg)
 | 
			
		||||
				que.UnFinMsg.Delete(conn)
 | 
			
		||||
				if len(msg) == lastID {
 | 
			
		||||
					return nil
 | 
			
		||||
				}
 | 
			
		||||
				msg = msg[lastID:]
 | 
			
		||||
				return que.parseMessage(msg, conn)
 | 
			
		||||
			}
 | 
			
		||||
			lastMsg.RecvMsg = bytesMerge(lastMsg.RecvMsg, msg)
 | 
			
		||||
			que.UnFinMsg.Store(conn, lastMsg)
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(msg) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	var start int
 | 
			
		||||
	if start = searchHeader(msg); start == -1 {
 | 
			
		||||
		return errors.New("data format error")
 | 
			
		||||
	}
 | 
			
		||||
	msg = msg[start:]
 | 
			
		||||
	lastMsg := unFinMsg{}
 | 
			
		||||
	que.UnFinMsg.Store(conn, &lastMsg)
 | 
			
		||||
	return que.parseMessage(msg, conn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkHeader(msg []byte) bool {
 | 
			
		||||
	if len(msg) != 8 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range msg {
 | 
			
		||||
		if v != header[k] {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func searchHeader(msg []byte) int {
 | 
			
		||||
	if len(msg) < 8 {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range msg {
 | 
			
		||||
		find := 0
 | 
			
		||||
		if v == header[0] {
 | 
			
		||||
			for k2, v2 := range header {
 | 
			
		||||
				if msg[k+k2] == v2 {
 | 
			
		||||
					find++
 | 
			
		||||
				} else {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if find == 8 {
 | 
			
		||||
				return k
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bytesMerge(src ...[]byte) []byte {
 | 
			
		||||
	var buff bytes.Buffer
 | 
			
		||||
	for _, v := range src {
 | 
			
		||||
		buff.Write(v)
 | 
			
		||||
	}
 | 
			
		||||
	return buff.Bytes()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Restore 获取收到的信息
 | 
			
		||||
func (que *StarQueue) Restore() (MsgQueue, error) {
 | 
			
		||||
	if que.duration.Seconds() == 0 {
 | 
			
		||||
		que.duration = 86400 * time.Second
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-que.ctx.Done():
 | 
			
		||||
			return MsgQueue{}, errors.New("Stoped By External Function Call")
 | 
			
		||||
		case <-time.After(que.duration):
 | 
			
		||||
			if que.duration != 0 {
 | 
			
		||||
				return MsgQueue{}, os.ErrDeadlineExceeded
 | 
			
		||||
			}
 | 
			
		||||
		case data, ok := <-que.MsgPool:
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return MsgQueue{}, os.ErrClosed
 | 
			
		||||
			}
 | 
			
		||||
			return data, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RestoreOne 获取收到的一个信息
 | 
			
		||||
//兼容性修改
 | 
			
		||||
func (que *StarQueue) RestoreOne() (MsgQueue, error) {
 | 
			
		||||
	return que.Restore()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Stop 立即停止Restore
 | 
			
		||||
func (que *StarQueue) Stop() {
 | 
			
		||||
	que.cancel()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// RestoreDuration Restore最大超时时间
 | 
			
		||||
func (que *StarQueue) RestoreDuration(tm time.Duration) {
 | 
			
		||||
	que.duration = tm
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (que *StarQueue) RestoreChan() <-chan MsgQueue {
 | 
			
		||||
	return que.MsgPool
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								vendor/b612.me/staros/beep_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								vendor/b612.me/staros/beep_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
// +build darwin
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// DefaultFreq - frequency, in Hz, middle A
 | 
			
		||||
	DefaultFreq = 0.0
 | 
			
		||||
	// DefaultDuration - duration in milliseconds
 | 
			
		||||
	DefaultDuration = 0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker).
 | 
			
		||||
func Beep(freq float64, duration int) error {
 | 
			
		||||
	osa, err := exec.LookPath("osascript")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// Output the only beep we can
 | 
			
		||||
		_, err = os.Stdout.Write([]byte{7})
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd := exec.Command(osa, "-e", `beep`)
 | 
			
		||||
	return cmd.Run()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										138
									
								
								vendor/b612.me/staros/beep_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								vendor/b612.me/staros/beep_linux.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,138 @@
 | 
			
		||||
// +build linux
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Constants
 | 
			
		||||
const (
 | 
			
		||||
	// This number represents the fixed frequency of the original PC XT's timer chip, which is approximately 1.193 MHz. This number
 | 
			
		||||
	// is divided with the desired frequency to obtain a counter value, that is subsequently fed into the timer chip, tied to the PC speaker.
 | 
			
		||||
	clockTickRate = 1193180
 | 
			
		||||
 | 
			
		||||
	// linux/kd.h, start sound generation (0 for off)
 | 
			
		||||
	kiocsound = 0x4B2F
 | 
			
		||||
 | 
			
		||||
	// linux/input-event-codes.h
 | 
			
		||||
	evSnd   = 0x12 // Event type
 | 
			
		||||
	sndTone = 0x02 // Sound
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// DefaultFreq - frequency, in Hz, middle A
 | 
			
		||||
	DefaultFreq = 440.0
 | 
			
		||||
	// DefaultDuration - duration in milliseconds
 | 
			
		||||
	DefaultDuration = 200
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// inputEvent represents linux/input.h event structure.
 | 
			
		||||
type inputEvent struct {
 | 
			
		||||
	Time  syscall.Timeval // time in seconds since epoch at which event occurred
 | 
			
		||||
	Type  uint16          // event type
 | 
			
		||||
	Code  uint16          // event code related to the event type
 | 
			
		||||
	Value int32           // event value related to the event type
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ioctl system call manipulates the underlying device parameters of special files.
 | 
			
		||||
func ioctl(fd, name, data uintptr) error {
 | 
			
		||||
	_, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, name, data)
 | 
			
		||||
	if e != 0 {
 | 
			
		||||
		return e
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker).
 | 
			
		||||
//
 | 
			
		||||
// On Linux it needs permission to access `/dev/tty0` or `/dev/input/by-path/platform-pcspkr-event-spkr` files for writing,
 | 
			
		||||
// and `pcspkr` module must be loaded. User must be in correct groups, usually `input` and/or `tty`.
 | 
			
		||||
//
 | 
			
		||||
// If it can not open device files, it will fallback to sending Bell character (https://en.wikipedia.org/wiki/Bell_character).
 | 
			
		||||
// For bell character in X11 terminals you can enable bell with `xset b on`. For console check `setterm` and `--blength` or `--bfreq` options.
 | 
			
		||||
//
 | 
			
		||||
// On macOS this just sends bell character. Enable `Audible bell` in Terminal --> Preferences --> Settings --> Advanced.
 | 
			
		||||
//
 | 
			
		||||
// On Windows it uses Beep function via syscall.
 | 
			
		||||
//
 | 
			
		||||
// On Web it plays hard coded beep sound.
 | 
			
		||||
func Beep(freq float64, duration int) error {
 | 
			
		||||
	if freq == 0 {
 | 
			
		||||
		freq = DefaultFreq
 | 
			
		||||
	} else if freq > 20000 {
 | 
			
		||||
		freq = 20000
 | 
			
		||||
	} else if freq < 0 {
 | 
			
		||||
		freq = DefaultFreq
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if duration == 0 {
 | 
			
		||||
		duration = DefaultDuration
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	period := int(float64(clockTickRate) / freq)
 | 
			
		||||
 | 
			
		||||
	var evdev bool
 | 
			
		||||
 | 
			
		||||
	f, err := os.OpenFile("/dev/tty0", os.O_WRONLY, 0644)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		e := err
 | 
			
		||||
		f, err = os.OpenFile("/dev/input/by-path/platform-pcspkr-event-spkr", os.O_WRONLY, 0644)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			e = errors.New("beeep: " + e.Error() + "; " + err.Error())
 | 
			
		||||
 | 
			
		||||
			// Output the only beep we can
 | 
			
		||||
			_, err = os.Stdout.Write([]byte{7})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return errors.New(e.Error() + "; " + err.Error())
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		evdev = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	defer f.Close()
 | 
			
		||||
 | 
			
		||||
	if evdev { // Use Linux evdev API
 | 
			
		||||
		ev := inputEvent{}
 | 
			
		||||
		ev.Type = evSnd
 | 
			
		||||
		ev.Code = sndTone
 | 
			
		||||
		ev.Value = int32(freq)
 | 
			
		||||
 | 
			
		||||
		d := *(*[unsafe.Sizeof(ev)]byte)(unsafe.Pointer(&ev))
 | 
			
		||||
 | 
			
		||||
		// Start beep
 | 
			
		||||
		f.Write(d[:])
 | 
			
		||||
 | 
			
		||||
		time.Sleep(time.Duration(duration) * time.Millisecond)
 | 
			
		||||
 | 
			
		||||
		ev.Value = 0
 | 
			
		||||
		d = *(*[unsafe.Sizeof(ev)]byte)(unsafe.Pointer(&ev))
 | 
			
		||||
 | 
			
		||||
		// Stop beep
 | 
			
		||||
		f.Write(d[:])
 | 
			
		||||
	} else { // Use ioctl
 | 
			
		||||
		// Start beep
 | 
			
		||||
		err = ioctl(f.Fd(), kiocsound, uintptr(period))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		time.Sleep(time.Duration(duration) * time.Millisecond)
 | 
			
		||||
 | 
			
		||||
		// Stop beep
 | 
			
		||||
		err = ioctl(f.Fd(), kiocsound, uintptr(0))
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								vendor/b612.me/staros/beep_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								vendor/b612.me/staros/beep_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// DefaultFreq - frequency, in Hz, middle A
 | 
			
		||||
	DefaultFreq = 587.0
 | 
			
		||||
	// DefaultDuration - duration in milliseconds
 | 
			
		||||
	DefaultDuration = 500
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Beep beeps the PC speaker (https://en.wikipedia.org/wiki/PC_speaker).
 | 
			
		||||
func Beep(freq float64, duration int) error {
 | 
			
		||||
	if freq == 0 {
 | 
			
		||||
		freq = DefaultFreq
 | 
			
		||||
	} else if freq > 32767 {
 | 
			
		||||
		freq = 32767
 | 
			
		||||
	} else if freq < 37 {
 | 
			
		||||
		freq = DefaultFreq
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if duration == 0 {
 | 
			
		||||
		duration = DefaultDuration
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	kernel32, _ := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	beep32, _ := syscall.GetProcAddress(kernel32, "Beep")
 | 
			
		||||
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
 | 
			
		||||
	_, _, e := syscall.Syscall(uintptr(beep32), uintptr(2), uintptr(int(freq)), uintptr(duration), 0)
 | 
			
		||||
	if e != 0 {
 | 
			
		||||
		return e
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								vendor/b612.me/staros/files.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								vendor/b612.me/staros/files.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var ERR_ALREADY_LOCKED = errors.New("ALREADY LOCKED")
 | 
			
		||||
var ERR_TIMEOUT = errors.New("TIME OUT")
 | 
			
		||||
 | 
			
		||||
func NewFileLock(filepath string) FileLock {
 | 
			
		||||
	return FileLock{
 | 
			
		||||
		filepath: filepath,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 检测文件/文件夹是否存在
 | 
			
		||||
func Exists(path string) bool {
 | 
			
		||||
	_, err := os.Stat(path)
 | 
			
		||||
	if err != nil && os.IsNotExist(err) {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsFile 返回给定文件地址是否是一个文件,
 | 
			
		||||
//True为是一个文件,False为不是文件或路径无效
 | 
			
		||||
func IsFile(fpath string) bool {
 | 
			
		||||
	s, err := os.Stat(fpath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return !s.IsDir()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsFolder 返回给定文件地址是否是一个文件夹,
 | 
			
		||||
//True为是一个文件夹,False为不是文件夹或路径无效
 | 
			
		||||
func IsFolder(fpath string) bool {
 | 
			
		||||
	s, err := os.Stat(fpath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return s.IsDir()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								vendor/b612.me/staros/files_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/b612.me/staros/files_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
//+build darwin
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/stario"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type FileLock struct {
 | 
			
		||||
	fd       int
 | 
			
		||||
	filepath string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) openFileForLock() error {
 | 
			
		||||
	fd, err := syscall.Open(f.filepath, syscall.O_CREAT|syscall.O_RDONLY, 0600)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	f.filepath = f.filepath
 | 
			
		||||
	f.fd = fd
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) Lock(Exclusive bool) error {
 | 
			
		||||
	var lockType int
 | 
			
		||||
	if Exclusive {
 | 
			
		||||
		lockType = syscall.LOCK_EX
 | 
			
		||||
	} else {
 | 
			
		||||
		lockType = syscall.LOCK_SH
 | 
			
		||||
	}
 | 
			
		||||
	if err := f.openFileForLock(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return syscall.Flock(f.fd, lockType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) LockNoBlocking(Exclusive bool) error {
 | 
			
		||||
	var lockType int
 | 
			
		||||
	if Exclusive {
 | 
			
		||||
		lockType = syscall.LOCK_EX
 | 
			
		||||
	} else {
 | 
			
		||||
		lockType = syscall.LOCK_SH
 | 
			
		||||
	}
 | 
			
		||||
	if err := f.openFileForLock(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	err := syscall.Flock(f.fd, lockType|syscall.LOCK_NB)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		syscall.Close(f.fd)
 | 
			
		||||
		if err == syscall.EWOULDBLOCK {
 | 
			
		||||
			return ERR_ALREADY_LOCKED
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) Unlock() error {
 | 
			
		||||
	err := syscall.Flock(f.fd, syscall.LOCK_UN)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return syscall.Close(f.fd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) LockWithTimeout(tm time.Duration, Exclusive bool) error {
 | 
			
		||||
	return stario.WaitUntilTimeout(tm, func(tmout chan struct{}) error {
 | 
			
		||||
		err := f.Lock(Exclusive)
 | 
			
		||||
		select {
 | 
			
		||||
		case <-tmout:
 | 
			
		||||
			f.Unlock()
 | 
			
		||||
			return nil
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timespecToTime(ts syscall.Timespec) time.Time {
 | 
			
		||||
	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
 | 
			
		||||
	return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Ctimespec)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
 | 
			
		||||
	return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Atimespec)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								vendor/b612.me/staros/files_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								vendor/b612.me/staros/files_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
//+build linux
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/stario"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type FileLock struct {
 | 
			
		||||
	fd       int
 | 
			
		||||
	filepath string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func timespecToTime(ts syscall.Timespec) time.Time {
 | 
			
		||||
	return time.Unix(int64(ts.Sec), int64(ts.Nsec))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
 | 
			
		||||
	return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Ctim)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
 | 
			
		||||
	return timespecToTime(fileinfo.Sys().(*syscall.Stat_t).Atim)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) openFileForLock() error {
 | 
			
		||||
	fd, err := syscall.Open(f.filepath, syscall.O_CREAT|syscall.O_RDONLY, 0600)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	f.filepath = f.filepath
 | 
			
		||||
	f.fd = fd
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) Lock(Exclusive bool) error {
 | 
			
		||||
	var lockType int
 | 
			
		||||
	if Exclusive {
 | 
			
		||||
		lockType = syscall.LOCK_EX
 | 
			
		||||
	} else {
 | 
			
		||||
		lockType = syscall.LOCK_SH
 | 
			
		||||
	}
 | 
			
		||||
	if err := f.openFileForLock(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return syscall.Flock(f.fd, lockType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) LockNoBlocking(Exclusive bool) error {
 | 
			
		||||
	var lockType int
 | 
			
		||||
	if Exclusive {
 | 
			
		||||
		lockType = syscall.LOCK_EX
 | 
			
		||||
	} else {
 | 
			
		||||
		lockType = syscall.LOCK_SH
 | 
			
		||||
	}
 | 
			
		||||
	if err := f.openFileForLock(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	err := syscall.Flock(f.fd, lockType|syscall.LOCK_NB)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		syscall.Close(f.fd)
 | 
			
		||||
		if err == syscall.EWOULDBLOCK {
 | 
			
		||||
			return ERR_ALREADY_LOCKED
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) Unlock() error {
 | 
			
		||||
	err := syscall.Flock(f.fd, syscall.LOCK_UN)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return syscall.Close(f.fd)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) LockWithTimeout(tm time.Duration, Exclusive bool) error {
 | 
			
		||||
	return stario.WaitUntilTimeout(tm, func(tmout chan struct{}) error {
 | 
			
		||||
		err := f.Lock(Exclusive)
 | 
			
		||||
		select {
 | 
			
		||||
		case <-tmout:
 | 
			
		||||
			f.Unlock()
 | 
			
		||||
			return nil
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		return err
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										123
									
								
								vendor/b612.me/staros/files_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								vendor/b612.me/staros/files_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,123 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/win32api"
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type FileLock struct {
 | 
			
		||||
	filepath string
 | 
			
		||||
	handle   win32api.HANDLE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFileCreationTime(fileinfo os.FileInfo) time.Time {
 | 
			
		||||
	d := fileinfo.Sys().(*syscall.Win32FileAttributeData)
 | 
			
		||||
	return time.Unix(0, d.CreationTime.Nanoseconds())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFileAccessTime(fileinfo os.FileInfo) time.Time {
 | 
			
		||||
	d := fileinfo.Sys().(*syscall.Win32FileAttributeData)
 | 
			
		||||
	return time.Unix(0, d.LastAccessTime.Nanoseconds())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetFileTimes(file *os.File, info os.FileInfo) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetFileTimesbyTime(file *os.File) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) openFileForLock() error {
 | 
			
		||||
	name, err := syscall.UTF16PtrFromString(f.filepath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	handle, err := syscall.CreateFile(
 | 
			
		||||
		name,
 | 
			
		||||
		syscall.GENERIC_READ,
 | 
			
		||||
		syscall.FILE_SHARE_READ,
 | 
			
		||||
		nil,
 | 
			
		||||
		syscall.OPEN_ALWAYS,
 | 
			
		||||
		syscall.FILE_FLAG_OVERLAPPED|0x00000080,
 | 
			
		||||
		0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	f.handle = win32api.HANDLE(handle)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) lockForTimeout(timeout time.Duration, lockType win32api.DWORD) error {
 | 
			
		||||
	var err error
 | 
			
		||||
	if err = f.openFileForLock(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	event, err := win32api.CreateEventW(nil, true, false, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	myEvent := &syscall.Overlapped{HEvent: syscall.Handle(event)}
 | 
			
		||||
	defer syscall.CloseHandle(myEvent.HEvent)
 | 
			
		||||
	_, err = win32api.LockFileEx(f.handle, lockType, 0, 1, 0, myEvent)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	if err != syscall.ERROR_IO_PENDING {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	millis := uint32(syscall.INFINITE)
 | 
			
		||||
	if timeout >= 0 {
 | 
			
		||||
		millis = uint32(timeout.Nanoseconds() / 1000000)
 | 
			
		||||
	}
 | 
			
		||||
	s, err := syscall.WaitForSingleObject(myEvent.HEvent, millis)
 | 
			
		||||
	switch s {
 | 
			
		||||
	case syscall.WAIT_OBJECT_0:
 | 
			
		||||
		// success!
 | 
			
		||||
		return nil
 | 
			
		||||
	case syscall.WAIT_TIMEOUT:
 | 
			
		||||
		f.Unlock()
 | 
			
		||||
		return ERR_TIMEOUT
 | 
			
		||||
	default:
 | 
			
		||||
		f.Unlock()
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) Lock(Exclusive bool) error {
 | 
			
		||||
	var lockType win32api.DWORD
 | 
			
		||||
	if Exclusive {
 | 
			
		||||
		lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK
 | 
			
		||||
	} else {
 | 
			
		||||
		lockType = 0
 | 
			
		||||
	}
 | 
			
		||||
	return f.lockForTimeout(0, lockType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) LockWithTimeout(tm time.Duration, Exclusive bool) error {
 | 
			
		||||
	var lockType win32api.DWORD
 | 
			
		||||
	if Exclusive {
 | 
			
		||||
		lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK
 | 
			
		||||
	} else {
 | 
			
		||||
		lockType = 0
 | 
			
		||||
	}
 | 
			
		||||
	return f.lockForTimeout(tm, lockType)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) LockNoBlocking(Exclusive bool) error {
 | 
			
		||||
	var lockType win32api.DWORD
 | 
			
		||||
	if Exclusive {
 | 
			
		||||
		lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK
 | 
			
		||||
	} else {
 | 
			
		||||
		lockType = 0
 | 
			
		||||
	}
 | 
			
		||||
	return f.lockForTimeout(0, lockType|win32api.LOCKFILE_FAIL_IMMEDIATELY)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FileLock) Unlock() error {
 | 
			
		||||
	return syscall.Close(syscall.Handle(f.handle))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										305
									
								
								vendor/b612.me/staros/math.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										305
									
								
								vendor/b612.me/staros/math.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,305 @@
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Calc(math string) (float64, error) {
 | 
			
		||||
	math = strings.Replace(math, " ", "", -1)
 | 
			
		||||
	math = strings.ToLower(math)
 | 
			
		||||
	if err := check(math); err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	result,err:=calc(math)
 | 
			
		||||
	if err!=nil {
 | 
			
		||||
		return 0,err
 | 
			
		||||
	}
 | 
			
		||||
	return floatRound(result,15),nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func floatRound(f float64, n int) float64 {
 | 
			
		||||
	format := "%." + strconv.Itoa(n) + "f"
 | 
			
		||||
	res, _ := strconv.ParseFloat(fmt.Sprintf(format, f), 64)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func check(math string) error {
 | 
			
		||||
	math = strings.Replace(math, " ", "", -1)
 | 
			
		||||
	math = strings.ToLower(math)
 | 
			
		||||
	var bracketSum int
 | 
			
		||||
	var signReady bool
 | 
			
		||||
	for k, v := range math {
 | 
			
		||||
		if string([]rune{v}) == "(" {
 | 
			
		||||
			bracketSum++
 | 
			
		||||
		}
 | 
			
		||||
		if string([]rune{v}) == ")" {
 | 
			
		||||
			bracketSum--
 | 
			
		||||
		}
 | 
			
		||||
		if bracketSum < 0 {
 | 
			
		||||
			return fmt.Errorf("err at position %d.Reason is right bracket position not correct,except (", k)
 | 
			
		||||
		}
 | 
			
		||||
		if containSign(string([]rune{v})) {
 | 
			
		||||
			if signReady {
 | 
			
		||||
				if string([]rune{v}) != "+" && string([]rune{v}) != "-" {
 | 
			
		||||
					return fmt.Errorf("err at position %d.Reason is sign %s not correct", k, string([]rune{v}))
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				signReady = true
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		signReady = false
 | 
			
		||||
	}
 | 
			
		||||
	if bracketSum != 0 {
 | 
			
		||||
		return fmt.Errorf("Error:right bracket is not equal as left bracket")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func calc(math string) (float64, error) {
 | 
			
		||||
	var bracketLeft int
 | 
			
		||||
	var bracketRight int
 | 
			
		||||
	var DupStart int = -1
 | 
			
		||||
	for pos, str := range math {
 | 
			
		||||
		if string(str) == "(" {
 | 
			
		||||
			bracketLeft = pos
 | 
			
		||||
		}
 | 
			
		||||
		if string(str) == ")" {
 | 
			
		||||
			bracketRight = pos
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if bracketRight == 0 && bracketLeft != 0 || (bracketLeft > bracketRight) {
 | 
			
		||||
		return 0, fmt.Errorf("Error:bracket not correct at %d ,except )", bracketLeft)
 | 
			
		||||
	}
 | 
			
		||||
	if bracketRight == 0 && bracketLeft == 0 {
 | 
			
		||||
		return calcLong(math)
 | 
			
		||||
	}
 | 
			
		||||
	line := math[bracketLeft+1 : bracketRight]
 | 
			
		||||
	num, err := calcLong(line)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	for i := bracketLeft - 1; i >= 0; i-- {
 | 
			
		||||
		if !containSign(math[i : i+1]) {
 | 
			
		||||
			DupStart = i
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		break
 | 
			
		||||
	}
 | 
			
		||||
	if DupStart != -1 {
 | 
			
		||||
		sign := math[DupStart:bracketLeft]
 | 
			
		||||
		num, err := calcDuaFloat(sign, num)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		math = math[:DupStart] + fmt.Sprintf("%.15f", num) + math[bracketRight+1:]
 | 
			
		||||
		DupStart = -1
 | 
			
		||||
	} else {
 | 
			
		||||
		math = math[:bracketLeft] + fmt.Sprintf("%.15f", num) + math[bracketRight+1:]
 | 
			
		||||
	}
 | 
			
		||||
	return calc(math)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func calcLong(str string) (float64, error) {
 | 
			
		||||
	var sigReady bool = false
 | 
			
		||||
	var sigApply bool = false
 | 
			
		||||
	var numPool []float64
 | 
			
		||||
	var operPool []string
 | 
			
		||||
	var numStr string
 | 
			
		||||
	var oper string
 | 
			
		||||
	if str[0:1] == "+" || str[0:1] == "-" {
 | 
			
		||||
		sigReady = true
 | 
			
		||||
	}
 | 
			
		||||
	for _, stp := range str {
 | 
			
		||||
		if sigReady && containSign(string(stp)) {
 | 
			
		||||
			sigReady = false
 | 
			
		||||
			sigApply = true
 | 
			
		||||
			oper = string(stp)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if !containSign(string(stp)) {
 | 
			
		||||
			sigReady = false
 | 
			
		||||
			numStr = string(append([]rune(numStr), stp))
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if !sigReady {
 | 
			
		||||
			sigReady = true
 | 
			
		||||
		}
 | 
			
		||||
		if sigApply {
 | 
			
		||||
			num, err := calcDua(oper, numStr)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return 0, err
 | 
			
		||||
			}
 | 
			
		||||
			sigApply = false
 | 
			
		||||
			numPool = append(numPool, num)
 | 
			
		||||
		} else {
 | 
			
		||||
			num, err := parseNumbic(numStr)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return 0, err
 | 
			
		||||
			}
 | 
			
		||||
			numPool = append(numPool, num)
 | 
			
		||||
		}
 | 
			
		||||
		numStr = ""
 | 
			
		||||
		operPool = append(operPool, string(stp))
 | 
			
		||||
	}
 | 
			
		||||
	if sigApply {
 | 
			
		||||
		num, err := calcDua(oper, numStr)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		numPool = append(numPool, num)
 | 
			
		||||
	} else {
 | 
			
		||||
		num, err := parseNumbic(numStr)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		numPool = append(numPool, num)
 | 
			
		||||
	}
 | 
			
		||||
	return calcPool(numPool, operPool)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func calcPool(numPool []float64, operPool []string) (float64, error) {
 | 
			
		||||
	if len(numPool) == 1 && len(operPool) == 0 {
 | 
			
		||||
		return numPool[0], nil
 | 
			
		||||
	}
 | 
			
		||||
	if len(numPool) < len(operPool) {
 | 
			
		||||
		return 0, errors.New(("Operate Signal Is too much"))
 | 
			
		||||
	}
 | 
			
		||||
	calcFunc := func(k int, v string) (float64, error) {
 | 
			
		||||
		num, err := calcSigFloat(numPool[k], v, numPool[k+1])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return 0, err
 | 
			
		||||
		}
 | 
			
		||||
		tmp := append(numPool[:k], num)
 | 
			
		||||
		numPool = append(tmp, numPool[k+2:]...)
 | 
			
		||||
		operPool = append(operPool[:k], operPool[k+1:]...)
 | 
			
		||||
		return calcPool(numPool, operPool)
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range operPool {
 | 
			
		||||
		if v == "^" {
 | 
			
		||||
			return calcFunc(k, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range operPool {
 | 
			
		||||
		if v == "*" || v == "/" {
 | 
			
		||||
			return calcFunc(k, v)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for k, v := range operPool {
 | 
			
		||||
		return calcFunc(k, v)
 | 
			
		||||
	}
 | 
			
		||||
	return 0, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func calcSigFloat(floatA float64, b string, floatC float64) (float64, error) {
 | 
			
		||||
	switch b {
 | 
			
		||||
	case "+":
 | 
			
		||||
		return floatRound(floatA + floatC,15), nil
 | 
			
		||||
	case "-":
 | 
			
		||||
		return floatRound(floatA - floatC,15), nil
 | 
			
		||||
	case "*":
 | 
			
		||||
		return floatRound(floatA * floatC,15), nil
 | 
			
		||||
	case "/":
 | 
			
		||||
		if floatC == 0 {
 | 
			
		||||
			return 0, errors.New("Divisor cannot be 0")
 | 
			
		||||
		}
 | 
			
		||||
		return floatRound(floatA / floatC,15), nil
 | 
			
		||||
	case "^":
 | 
			
		||||
		return math.Pow(floatA, floatC), nil
 | 
			
		||||
	}
 | 
			
		||||
	return 0, fmt.Errorf("unexpect method:%s", b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func calcSig(a, b, c string) (float64, error) {
 | 
			
		||||
	floatA, err := parseNumbic(a)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	floatC, err := parseNumbic(c)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return calcSigFloat(floatA, b, floatC)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func calcDuaFloat(a string, floatB float64) (float64, error) {
 | 
			
		||||
	switch a {
 | 
			
		||||
	case "sin":
 | 
			
		||||
		return math.Sin(floatB), nil
 | 
			
		||||
	case "cos":
 | 
			
		||||
		return math.Cos(floatB), nil
 | 
			
		||||
	case "tan":
 | 
			
		||||
		return math.Tan(floatB), nil
 | 
			
		||||
	case "abs":
 | 
			
		||||
		return math.Abs(floatB), nil
 | 
			
		||||
	case "arcsin":
 | 
			
		||||
		return math.Asin(floatB), nil
 | 
			
		||||
	case "arccos":
 | 
			
		||||
		return math.Acos(floatB), nil
 | 
			
		||||
	case "arctan":
 | 
			
		||||
		return math.Atan(floatB), nil
 | 
			
		||||
	case "sqrt":
 | 
			
		||||
		return math.Sqrt(floatB), nil
 | 
			
		||||
	case "loge":
 | 
			
		||||
		return math.Log(floatB), nil
 | 
			
		||||
	case "log10":
 | 
			
		||||
		return math.Log10(floatB), nil
 | 
			
		||||
	case "log2":
 | 
			
		||||
		return math.Log2(floatB), nil
 | 
			
		||||
	case "floor":
 | 
			
		||||
		return math.Floor(floatB), nil
 | 
			
		||||
	case "ceil":
 | 
			
		||||
		return math.Ceil(floatB), nil
 | 
			
		||||
	case "round":
 | 
			
		||||
		return math.Round(floatB), nil
 | 
			
		||||
	case "trunc":
 | 
			
		||||
		return math.Trunc(floatB), nil
 | 
			
		||||
	case "+":
 | 
			
		||||
		return 0 + floatB, nil
 | 
			
		||||
	case "-":
 | 
			
		||||
		return 0 - floatB, nil
 | 
			
		||||
	}
 | 
			
		||||
	return 0, fmt.Errorf("unexpect method:%s", a)
 | 
			
		||||
}
 | 
			
		||||
func calcDua(a, b string) (float64, error) {
 | 
			
		||||
	floatB, err := parseNumbic(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	return calcDuaFloat(a, floatB)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseNumbic(str string) (float64, error) {
 | 
			
		||||
	switch str {
 | 
			
		||||
	case "pi":
 | 
			
		||||
		return float64(math.Pi), nil
 | 
			
		||||
	case "e":
 | 
			
		||||
		return float64(math.E), nil
 | 
			
		||||
	default:
 | 
			
		||||
		return strconv.ParseFloat(str, 64)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func containSign(str string) bool {
 | 
			
		||||
	var sign []string = []string{"+", "-", "*", "/", "^"}
 | 
			
		||||
	for _, v := range sign {
 | 
			
		||||
		if str == v {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func contain(pool []string, str string) bool {
 | 
			
		||||
	for _, v := range pool {
 | 
			
		||||
		if v == str {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										101
									
								
								vendor/b612.me/staros/memory_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								vendor/b612.me/staros/memory_darwin.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,101 @@
 | 
			
		||||
//+build darwin
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"golang.org/x/sys/unix"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Memory 系统内存信息
 | 
			
		||||
func Memory() (MemStatus,error) {
 | 
			
		||||
	return darwinMemory()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type swapUsage struct {
 | 
			
		||||
	Total     uint64
 | 
			
		||||
	Avail     uint64
 | 
			
		||||
	Used      uint64
 | 
			
		||||
	Pagesize  int32
 | 
			
		||||
	Encrypted bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func darwinMemory() (MemStatus, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	var res MemStatus
 | 
			
		||||
	vm_stat, err := exec.LookPath("vm_stat")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
	out, err := exec.Command(vm_stat).CombinedOutput()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
	totalString, err := unix.Sysctl("hw.memsize")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// unix.sysctl() helpfully assumes the result is a null-terminated string and
 | 
			
		||||
	// removes the last byte of the result if it's 0 :/
 | 
			
		||||
	totalString += "\x00"
 | 
			
		||||
 | 
			
		||||
	res.All = uint64(binary.LittleEndian.Uint64([]byte(totalString)))
 | 
			
		||||
 | 
			
		||||
	lines := strings.Split(string(out), "\n")
 | 
			
		||||
	pagesize := uint64(unix.Getpagesize())
 | 
			
		||||
	for _, line := range lines {
 | 
			
		||||
		fields := strings.Split(line, ":")
 | 
			
		||||
		if len(fields) < 2 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		key := strings.TrimSpace(fields[0])
 | 
			
		||||
		value := strings.Trim(fields[1], " .")
 | 
			
		||||
		switch key {
 | 
			
		||||
		case "Pages free":
 | 
			
		||||
			free, e := strconv.ParseUint(value, 10, 64)
 | 
			
		||||
			if e != nil {
 | 
			
		||||
				err = e
 | 
			
		||||
			}
 | 
			
		||||
			res.Free = free * pagesize
 | 
			
		||||
		case "Pages inactive":
 | 
			
		||||
			inactive, e := strconv.ParseUint(value, 10, 64)
 | 
			
		||||
			if e != nil {
 | 
			
		||||
				err = e
 | 
			
		||||
			}
 | 
			
		||||
			res.Available = inactive * pagesize
 | 
			
		||||
		case "Pages active":
 | 
			
		||||
			active, e := strconv.ParseUint(value, 10, 64)
 | 
			
		||||
			if e != nil {
 | 
			
		||||
				err = e
 | 
			
		||||
			}
 | 
			
		||||
			_ = active * pagesize
 | 
			
		||||
		case "Pages wired down":
 | 
			
		||||
			wired, e := strconv.ParseUint(value, 10, 64)
 | 
			
		||||
			if e != nil {
 | 
			
		||||
				err = e
 | 
			
		||||
			}
 | 
			
		||||
			_ = wired * pagesize
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	res.Available += res.Free
 | 
			
		||||
	res.Used = res.All - res.Available
 | 
			
		||||
	//swap
 | 
			
		||||
	value, err := unix.SysctlRaw("vm.swapusage")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return res, err
 | 
			
		||||
	}
 | 
			
		||||
	if len(value) != 32 {
 | 
			
		||||
		return res, fmt.Errorf("unexpected output of sysctl vm.swapusage: %v (len: %d)", value, len(value))
 | 
			
		||||
	}
 | 
			
		||||
	swap := (*swapUsage)(unsafe.Pointer(&value[0]))
 | 
			
		||||
	res.SwapAll = swap.Total
 | 
			
		||||
	res.SwapUsed = swap.Used
 | 
			
		||||
	res.SwapFree = swap.Avail
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								vendor/b612.me/staros/memory_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/b612.me/staros/memory_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
//+build linux
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import "syscall"
 | 
			
		||||
 | 
			
		||||
// Memory 系统内存信息
 | 
			
		||||
func Memory() (MemStatus, error) {
 | 
			
		||||
	var mem MemStatus
 | 
			
		||||
	ram := new(syscall.Sysinfo_t)
 | 
			
		||||
	if err := syscall.Sysinfo(ram); err != nil {
 | 
			
		||||
		return mem, err
 | 
			
		||||
	}
 | 
			
		||||
	mem.All = uint64(ram.Totalram)
 | 
			
		||||
	mem.BuffCache = uint64(ram.Bufferram)
 | 
			
		||||
	mem.Free = uint64(ram.Freeram)
 | 
			
		||||
	mem.Shared = uint64(ram.Sharedram)
 | 
			
		||||
	mem.Available = uint64(ram.Freeram + ram.Sharedram + ram.Bufferram)
 | 
			
		||||
	mem.SwapAll = uint64(ram.Totalswap)
 | 
			
		||||
	mem.SwapFree = uint64(ram.Freeswap)
 | 
			
		||||
	mem.SwapUsed = uint64(mem.SwapAll - mem.SwapFree)
 | 
			
		||||
	mem.Used = uint64(mem.All - mem.Free)
 | 
			
		||||
	return mem, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								vendor/b612.me/staros/memory_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/b612.me/staros/memory_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import "b612.me/win32api"
 | 
			
		||||
 | 
			
		||||
// Memory 系统内存信息
 | 
			
		||||
func Memory() (MemStatus, error) {
 | 
			
		||||
	var mem MemStatus
 | 
			
		||||
	ram := new(win32api.MEMORYSTATUSEX)
 | 
			
		||||
	_, err := win32api.GlobalMemoryStatusEx(ram)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return mem, err
 | 
			
		||||
	}
 | 
			
		||||
	mem.All = uint64(ram.UllTotalPhys)
 | 
			
		||||
	mem.Free = uint64(ram.UllAvailPhys)
 | 
			
		||||
	mem.Available = uint64(ram.UllAvailPhys)
 | 
			
		||||
	mem.Used = uint64(mem.All - mem.Free)
 | 
			
		||||
	mem.SwapAll = uint64(ram.UllTotalPageFile)
 | 
			
		||||
	mem.SwapFree = uint64(ram.UllAvailPageFile)
 | 
			
		||||
	mem.SwapUsed = mem.SwapAll - mem.SwapFree
 | 
			
		||||
	mem.VirtualAll = uint64(mem.VirtualAll)
 | 
			
		||||
	mem.VirtualAvail = uint64(mem.VirtualAvail)
 | 
			
		||||
	mem.VirtualUsed = mem.VirtualAll - mem.VirtualUsed
 | 
			
		||||
	return mem, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										319
									
								
								vendor/b612.me/staros/network_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								vendor/b612.me/staros/network_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,319 @@
 | 
			
		||||
// +build !windows
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NetUsage() ([]NetAdapter, error) {
 | 
			
		||||
	data, err := ioutil.ReadFile("/proc/net/dev")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []NetAdapter{}, err
 | 
			
		||||
	}
 | 
			
		||||
	sps := strings.Split(strings.TrimSpace(string(data)), "\n")
 | 
			
		||||
	if len(sps) < 3 {
 | 
			
		||||
		return []NetAdapter{}, errors.New("No Adaptor")
 | 
			
		||||
	}
 | 
			
		||||
	var res []NetAdapter
 | 
			
		||||
	netLists := sps[2:]
 | 
			
		||||
	for _, v := range netLists {
 | 
			
		||||
		v = strings.ReplaceAll(v, "   ", "  ")
 | 
			
		||||
		for strings.Contains(v, "  ") {
 | 
			
		||||
			v = strings.ReplaceAll(v, "  ", " ")
 | 
			
		||||
		}
 | 
			
		||||
		v = strings.TrimSpace(v)
 | 
			
		||||
		card := strings.Split(v, " ")
 | 
			
		||||
		name := strings.ReplaceAll(card[0], ":", "")
 | 
			
		||||
		recvBytes, _ := strconv.Atoi(card[1])
 | 
			
		||||
		sendBytes, _ := strconv.Atoi(card[9])
 | 
			
		||||
		res = append(res, NetAdapter{name, uint64(recvBytes), uint64(sendBytes)})
 | 
			
		||||
	}
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NetUsageByname(name string) (NetAdapter, error) {
 | 
			
		||||
	ada, err := NetUsage()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return NetAdapter{}, err
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range ada {
 | 
			
		||||
		if v.Name == name {
 | 
			
		||||
			return v, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NetAdapter{}, errors.New("Not Found")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NetSpeeds(duration time.Duration) ([]NetSpeed, error) {
 | 
			
		||||
	list1, err := NetUsage()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []NetSpeed{}, err
 | 
			
		||||
	}
 | 
			
		||||
	time.Sleep(duration)
 | 
			
		||||
	list2, err := NetUsage()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return []NetSpeed{}, err
 | 
			
		||||
	}
 | 
			
		||||
	if len(list1) > len(list2) {
 | 
			
		||||
		return []NetSpeed{}, errors.New("NetWork Adaptor Num Not ok")
 | 
			
		||||
	}
 | 
			
		||||
	var res []NetSpeed
 | 
			
		||||
	for k, v := range list1 {
 | 
			
		||||
		recv := float64(list2[k].RecvBytes-v.RecvBytes) / duration.Seconds()
 | 
			
		||||
		send := float64(list2[k].SendBytes-v.SendBytes) / duration.Seconds()
 | 
			
		||||
		res = append(res, NetSpeed{v.Name, recv, send})
 | 
			
		||||
	}
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NetSpeedsByName(duration time.Duration, name string) (NetSpeed, error) {
 | 
			
		||||
	ada, err := NetSpeeds(duration)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return NetSpeed{}, err
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range ada {
 | 
			
		||||
		if v.Name == name {
 | 
			
		||||
			return v, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return NetSpeed{}, errors.New("Not Found")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NetConnections return all TCP/UDP/UNIX DOMAIN SOCKET Connections
 | 
			
		||||
// if your uid != 0 ,and analysePid==true ,you should have CAP_SYS_PRTACE and CAP_DAC_OVERRIDE/CAP_DAC_READ_SEARCH Caps
 | 
			
		||||
func NetConnections(analysePid bool,types string) ([]NetConn, error) {
 | 
			
		||||
	var result []NetConn
 | 
			
		||||
	var inodeMap map[string]int64
 | 
			
		||||
	var err error
 | 
			
		||||
	var fileList []string
 | 
			
		||||
	if types=="" || strings.Contains(strings.ToLower(types),"all") {
 | 
			
		||||
		fileList = []string{
 | 
			
		||||
			"/proc/net/tcp",
 | 
			
		||||
			"/proc/net/tcp6",
 | 
			
		||||
			"/proc/net/udp",
 | 
			
		||||
			"/proc/net/udp6",
 | 
			
		||||
			"/proc/net/unix",
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if strings.Contains(strings.ToLower(types),"tcp") {
 | 
			
		||||
		fileList =append(fileList,"/proc/net/tcp","/proc/net/tcp6")
 | 
			
		||||
	}
 | 
			
		||||
	if strings.Contains(strings.ToLower(types),"udp") {
 | 
			
		||||
		fileList =append(fileList,"/proc/net/udp","/proc/net/udp6")
 | 
			
		||||
	}
 | 
			
		||||
	if strings.Contains(strings.ToLower(types),"unix") {
 | 
			
		||||
		fileList =append(fileList,"/proc/net/unix")
 | 
			
		||||
	}
 | 
			
		||||
	if analysePid {
 | 
			
		||||
		inodeMap, err = GetInodeMap()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for _, file := range fileList {
 | 
			
		||||
		data, err := ioutil.ReadFile(file)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		tmpRes, err := analyseNetFiles(data, inodeMap, file[strings.LastIndex(file, "/")+1:])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		result = append(result, tmpRes...)
 | 
			
		||||
	}
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetInodeMap() (map[string]int64, error) {
 | 
			
		||||
	res := make(map[string]int64)
 | 
			
		||||
	paths, err := ioutil.ReadDir("/proc")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range paths {
 | 
			
		||||
		if v.IsDir() && Exists("/proc/"+v.Name()+"/fd") {
 | 
			
		||||
			fds, err := ioutil.ReadDir("/proc/" + v.Name() + "/fd")
 | 
			
		||||
			if err != nil && Exists("/proc/"+v.Name()+"/fd") {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			for _, fd := range fds {
 | 
			
		||||
				socket, err := os.Readlink("/proc/" + v.Name() + "/fd/" + fd.Name())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				if !strings.Contains(socket, "socket") {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				start := strings.Index(socket, "[")
 | 
			
		||||
				if start < 0 {
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				pid, err := strconv.ParseInt(v.Name(), 10, 64)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				res[socket[start+1:len(socket)-1]] = pid
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return res, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func analyseNetFiles(data []byte, inodeMap map[string]int64, typed string) ([]NetConn, error) {
 | 
			
		||||
	if typed == "unix" {
 | 
			
		||||
		return analyseUnixFiles(data, inodeMap, typed)
 | 
			
		||||
	}
 | 
			
		||||
	var result []NetConn
 | 
			
		||||
	strdata := strings.TrimSpace(string(data))
 | 
			
		||||
	strdata = remainOne(strdata, "  ", " ")
 | 
			
		||||
	csvData := strings.Split(strdata, "\n")
 | 
			
		||||
	pidMap := make(map[int64]*Process)
 | 
			
		||||
	for line, lineData := range csvData {
 | 
			
		||||
		if line == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		v := strings.Split(strings.TrimSpace(lineData), " ")
 | 
			
		||||
		var res NetConn
 | 
			
		||||
		ip, port, err := parseHexIpPort(v[1])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		res.LocalAddr = ip
 | 
			
		||||
		res.LocalPort = port
 | 
			
		||||
		ip, port, err = parseHexIpPort(v[2])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		res.RemoteAddr = ip
 | 
			
		||||
		res.RemotePort = port
 | 
			
		||||
		//connection state
 | 
			
		||||
		if strings.Contains(typed, "tcp") {
 | 
			
		||||
			state, err := strconv.ParseInt(strings.TrimSpace(v[3]), 16, 64)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return result, err
 | 
			
		||||
			}
 | 
			
		||||
			res.Status = TCP_STATE[state]
 | 
			
		||||
		}
 | 
			
		||||
		txrx_queue := strings.Split(strings.TrimSpace(v[4]), ":")
 | 
			
		||||
		if len(txrx_queue) != 2 {
 | 
			
		||||
			return result, errors.New("not a valid net file")
 | 
			
		||||
		}
 | 
			
		||||
		tx_queue, err := strconv.ParseInt(txrx_queue[0], 16, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		res.TX_Queue = tx_queue
 | 
			
		||||
		rx_queue, err := strconv.ParseInt(txrx_queue[1], 16, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		res.RX_Queue = rx_queue
 | 
			
		||||
		timer := strings.Split(strings.TrimSpace(v[5]), ":")
 | 
			
		||||
		if len(timer) != 2 {
 | 
			
		||||
			return result, errors.New("not a valid net file")
 | 
			
		||||
		}
 | 
			
		||||
		switch timer[0] {
 | 
			
		||||
		case "00":
 | 
			
		||||
			res.TimerActive = "NO_TIMER"
 | 
			
		||||
		case "01":
 | 
			
		||||
			//重传定时器
 | 
			
		||||
			res.TimerActive = "RETRANSMIT"
 | 
			
		||||
		case "02":
 | 
			
		||||
			//连接定时器、FIN_WAIT_2定时器或TCP保活定时器
 | 
			
		||||
			res.TimerActive = "KEEPALIVE"
 | 
			
		||||
		case "03":
 | 
			
		||||
			//TIME_WAIT定时器
 | 
			
		||||
			res.TimerActive = "TIME_WAIT"
 | 
			
		||||
		case "04":
 | 
			
		||||
			//持续定时器
 | 
			
		||||
			res.TimerActive = "ZERO_WINDOW_PROBE"
 | 
			
		||||
		default:
 | 
			
		||||
			res.TimerActive = "UNKNOWN"
 | 
			
		||||
		}
 | 
			
		||||
		timerJif, err := strconv.ParseInt(timer[1], 16, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		res.TimerJiffies = timerJif
 | 
			
		||||
		timerCnt, err := strconv.ParseInt(strings.TrimSpace(v[6]), 16, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		res.RtoTimer = timerCnt
 | 
			
		||||
		res.Uid, err = strconv.ParseInt(v[7], 10, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return result, err
 | 
			
		||||
		}
 | 
			
		||||
		res.Inode = v[9]
 | 
			
		||||
		if inodeMap != nil && len(inodeMap) > 0 {
 | 
			
		||||
			var ok bool
 | 
			
		||||
			res.Pid, ok = inodeMap[res.Inode]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				res.Pid = -1
 | 
			
		||||
			} else {
 | 
			
		||||
				_, ok := pidMap[res.Pid]
 | 
			
		||||
				if !ok {
 | 
			
		||||
					tmp, err := FindProcessByPid(res.Pid)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						pidMap[res.Pid] = nil
 | 
			
		||||
					} else {
 | 
			
		||||
						pidMap[res.Pid] = &tmp
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				res.Process = pidMap[res.Pid]
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		res.Typed = typed
 | 
			
		||||
		result = append(result, res)
 | 
			
		||||
	}
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func analyseUnixFiles(data []byte, inodeMap map[string]int64, typed string) ([]NetConn, error) {
 | 
			
		||||
	var result []NetConn
 | 
			
		||||
	strdata := strings.TrimSpace(string(data))
 | 
			
		||||
	strdata = remainOne(strdata, "  ", " ")
 | 
			
		||||
	csvData := strings.Split(strdata, "\n")
 | 
			
		||||
	pidMap := make(map[int64]*Process)
 | 
			
		||||
	for line, lineData := range csvData {
 | 
			
		||||
		if line == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		v := strings.Split(strings.TrimSpace(lineData), " ")
 | 
			
		||||
		var res NetConn
 | 
			
		||||
		res.Inode = v[6]
 | 
			
		||||
		if len(v) == 8 {
 | 
			
		||||
			res.Socket = v[7]
 | 
			
		||||
		}
 | 
			
		||||
		if inodeMap != nil && len(inodeMap) > 0 {
 | 
			
		||||
			var ok bool
 | 
			
		||||
			res.Pid, ok = inodeMap[res.Inode]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				res.Pid = -1
 | 
			
		||||
			} else {
 | 
			
		||||
				_, ok := pidMap[res.Pid]
 | 
			
		||||
				if !ok || pidMap[res.Pid] == nil {
 | 
			
		||||
					tmp, err := FindProcessByPid(res.Pid)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						pidMap[res.Pid] = nil
 | 
			
		||||
					} else {
 | 
			
		||||
						pidMap[res.Pid] = &tmp
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if pidMap[res.Pid] != nil {
 | 
			
		||||
					res.Uid = int64(pidMap[res.Pid].RUID)
 | 
			
		||||
					res.Process = pidMap[res.Pid]
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		res.Typed = typed
 | 
			
		||||
		result = append(result, res)
 | 
			
		||||
	}
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								vendor/b612.me/staros/network_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								vendor/b612.me/staros/network_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NetUsage() ([]NetAdapter, error) {
 | 
			
		||||
	var res []NetAdapter
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NetUsageByname(name string) (NetAdapter, error) {
 | 
			
		||||
	return NetAdapter{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NetSpeeds(duration time.Duration) ([]NetSpeed, error) {
 | 
			
		||||
	var res []NetSpeed
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NetSpeedsByName(duration time.Duration, name string) (NetSpeed, error) {
 | 
			
		||||
 | 
			
		||||
	return NetSpeed{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NetConnections return all TCP/UDP/UNIX DOMAIN SOCKET Connections
 | 
			
		||||
// if your uid != 0 ,and analysePid==true ,you should have CAP_SYS_PRTACE and CAP_DAC_OVERRIDE/CAP_DAC_READ_SEARCH Caps
 | 
			
		||||
func NetConnections(analysePid bool) ([]NetConn, error) {
 | 
			
		||||
	var result []NetConn
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								vendor/b612.me/staros/os.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								vendor/b612.me/staros/os.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os/user"
 | 
			
		||||
	"strconv"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetUidGid
 | 
			
		||||
func GetUidGid(uname string) (uint32, uint32, string, error) {
 | 
			
		||||
	usr, err := user.Lookup(uname)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, 0, "", err
 | 
			
		||||
	}
 | 
			
		||||
	uidInt, _ := strconv.Atoi(usr.Uid)
 | 
			
		||||
	gidInt, _ := strconv.Atoi(usr.Gid)
 | 
			
		||||
	return uint32(uidInt), uint32(gidInt), usr.HomeDir, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetUid
 | 
			
		||||
func GetUid(uname string) (uint32, error) {
 | 
			
		||||
	usr, err := user.Lookup(uname)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	uidInt, _ := strconv.Atoi(usr.Uid)
 | 
			
		||||
	return uint32(uidInt), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetGid
 | 
			
		||||
func GetGid(uname string) (uint32, error) {
 | 
			
		||||
	usr, err := user.LookupGroup(uname)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	gidInt, _ := strconv.Atoi(usr.Gid)
 | 
			
		||||
	return uint32(gidInt), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetGidByName
 | 
			
		||||
func GetGidByName(uname string) (uint32, error) {
 | 
			
		||||
	usr, err := user.Lookup(uname)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	uidInt, _ := strconv.Atoi(usr.Gid)
 | 
			
		||||
	return uint32(uidInt), nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										152
									
								
								vendor/b612.me/staros/os_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								vendor/b612.me/staros/os_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,152 @@
 | 
			
		||||
// +build linux darwin unix
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os/user"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var clockTicks = 100 // default value
 | 
			
		||||
 | 
			
		||||
// StartTime 开机时间
 | 
			
		||||
func StartTime() time.Time {
 | 
			
		||||
	tmp, _ := readAsString("/proc/stat")
 | 
			
		||||
	data := splitBy(ReplaceByte9(tmp), " ")
 | 
			
		||||
	btime, _ := strconv.ParseInt(strings.TrimSpace(data["btime"]), 10, 64)
 | 
			
		||||
	return time.Unix(btime, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsRoot 当前是否是管理员用户
 | 
			
		||||
func IsRoot() bool {
 | 
			
		||||
	uid, _ := user.Current()
 | 
			
		||||
	if uid.Uid == "0" {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Whoami() (uid, gid int, uname, gname, home string, err error) {
 | 
			
		||||
	var me *user.User
 | 
			
		||||
	var gup *user.Group
 | 
			
		||||
	me, err = user.Current()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	uid, _ = strconv.Atoi(me.Uid)
 | 
			
		||||
	gid, _ = strconv.Atoi(me.Uid)
 | 
			
		||||
	home = me.HomeDir
 | 
			
		||||
	uname = me.Username
 | 
			
		||||
	gup, err = user.LookupGroupId(me.Gid)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	gname = gup.Name
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getCPUSample() (idle, total uint64) {
 | 
			
		||||
	contents, err := ioutil.ReadFile("/proc/stat")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	lines := strings.Split(string(contents), "\n")
 | 
			
		||||
	for _, line := range lines {
 | 
			
		||||
		fields := strings.Fields(line)
 | 
			
		||||
		if fields[0] == "cpu" {
 | 
			
		||||
			numFields := len(fields)
 | 
			
		||||
			for i := 1; i < numFields; i++ {
 | 
			
		||||
				val, err := strconv.ParseUint(fields[i], 10, 64)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					fmt.Println("Error: ", i, fields[i], err)
 | 
			
		||||
				}
 | 
			
		||||
				total += val          // tally up all the numbers to get total ticks
 | 
			
		||||
				if i == 4 || i == 5 { // idle is the 5th field in the cpu line
 | 
			
		||||
					idle += val
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
func splitProcStat(content []byte) []string {
 | 
			
		||||
	nameStart := bytes.IndexByte(content, '(')
 | 
			
		||||
	nameEnd := bytes.LastIndexByte(content, ')')
 | 
			
		||||
	restFields := strings.Fields(string(content[nameEnd+2:])) // +2 skip ') '
 | 
			
		||||
	name := content[nameStart+1 : nameEnd]
 | 
			
		||||
	pid := strings.TrimSpace(string(content[:nameStart]))
 | 
			
		||||
	fields := make([]string, 3, len(restFields)+3)
 | 
			
		||||
	fields[1] = string(pid)
 | 
			
		||||
	fields[2] = string(name)
 | 
			
		||||
	fields = append(fields, restFields...)
 | 
			
		||||
	return fields
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getCPUSampleByPid(pid int) float64 {
 | 
			
		||||
	contents, err := ioutil.ReadFile("/proc/" + strconv.Itoa(pid) + "/stat")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	fields := splitProcStat(contents)
 | 
			
		||||
	utime, err := strconv.ParseFloat(fields[14], 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	stime, err := strconv.ParseFloat(fields[15], 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// There is no such thing as iotime in stat file.  As an approximation, we
 | 
			
		||||
	// will use delayacct_blkio_ticks (aggregated block I/O delays, as per Linux
 | 
			
		||||
	// docs).  Note: I am assuming at least Linux 2.6.18
 | 
			
		||||
	var iotime float64
 | 
			
		||||
	if len(fields) > 42 {
 | 
			
		||||
		iotime, err = strconv.ParseFloat(fields[42], 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			iotime = 0 // Ancient linux version, most likely
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		iotime = 0 // e.g. SmartOS containers
 | 
			
		||||
	}
 | 
			
		||||
	return utime/float64(clockTicks) + stime/float64(clockTicks) + iotime/float64(clockTicks)
 | 
			
		||||
}
 | 
			
		||||
func CpuUsageByPid(pid int, sleep time.Duration) float64 {
 | 
			
		||||
	total1 := getCPUSampleByPid(pid)
 | 
			
		||||
	time.Sleep(sleep)
 | 
			
		||||
	total2 := getCPUSampleByPid(pid)
 | 
			
		||||
	return (total2 - total1) / sleep.Seconds() * 100
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CpuUsage 获取CPU使用量
 | 
			
		||||
func CpuUsage(sleep time.Duration) float64 {
 | 
			
		||||
	idle0, total0 := getCPUSample()
 | 
			
		||||
	time.Sleep(sleep)
 | 
			
		||||
	idle1, total1 := getCPUSample()
 | 
			
		||||
	idleTicks := float64(idle1 - idle0)
 | 
			
		||||
	totalTicks := float64(total1 - total0)
 | 
			
		||||
	cpuUsage := 100 * (totalTicks - idleTicks) / totalTicks
 | 
			
		||||
	return cpuUsage
 | 
			
		||||
	//fmt.Printf("CPU usage is %f%% [busy: %f, total: %f]\n", cpuUsage, totalTicks-idleTicks, totalTicks)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DiskUsage(path string) (disk DiskStatus) {
 | 
			
		||||
	fs := syscall.Statfs_t{}
 | 
			
		||||
	err := syscall.Statfs(path, &fs)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	disk.All = fs.Blocks * uint64(fs.Bsize)
 | 
			
		||||
	disk.Free = fs.Bfree * uint64(fs.Bsize)
 | 
			
		||||
	disk.Available = fs.Bavail * uint64(fs.Bsize)
 | 
			
		||||
	disk.Used = disk.All - disk.Free
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								vendor/b612.me/staros/os_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								vendor/b612.me/staros/os_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,60 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"log"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"b612.me/wincmd"
 | 
			
		||||
 | 
			
		||||
	"b612.me/win32api"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// StartTime 开机时间
 | 
			
		||||
func StartTime() time.Time {
 | 
			
		||||
	data, _ := win32api.GetTickCount()
 | 
			
		||||
	date := float64(time.Now().Unix())
 | 
			
		||||
	unix := date - float64(data)/1000
 | 
			
		||||
	max := (unix - float64(int64(unix))) * 1000000000
 | 
			
		||||
	return time.Unix(int64(unix), int64(max))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsRoot 当前是否是管理员用户
 | 
			
		||||
func IsRoot() bool {
 | 
			
		||||
	return wincmd.Isas()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func DiskUsage(path string) (disk DiskStatus) {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("Kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Panic(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	GetDiskFreeSpaceEx, err := syscall.GetProcAddress(syscall.Handle(kernel32), "GetDiskFreeSpaceExW")
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lpFreeBytesAvailable := int64(0)
 | 
			
		||||
	lpTotalNumberOfBytes := int64(0)
 | 
			
		||||
	lpTotalNumberOfFreeBytes := int64(0)
 | 
			
		||||
	syscall.Syscall6(uintptr(GetDiskFreeSpaceEx), 4,
 | 
			
		||||
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr("C:"))),
 | 
			
		||||
		uintptr(unsafe.Pointer(&lpFreeBytesAvailable)),
 | 
			
		||||
		uintptr(unsafe.Pointer(&lpTotalNumberOfBytes)),
 | 
			
		||||
		uintptr(unsafe.Pointer(&lpTotalNumberOfFreeBytes)), 0, 0)
 | 
			
		||||
	disk.Free = uint64(lpTotalNumberOfFreeBytes)
 | 
			
		||||
	disk.Used = uint64(lpTotalNumberOfBytes - lpTotalNumberOfFreeBytes)
 | 
			
		||||
	disk.All = uint64(lpTotalNumberOfBytes)
 | 
			
		||||
	disk.Available = uint64(lpFreeBytesAvailable)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CpuUsage(sleep time.Duration) float64 {
 | 
			
		||||
	return 0
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										347
									
								
								vendor/b612.me/staros/process.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								vendor/b612.me/staros/process.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,347 @@
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"context"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"sync/atomic"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//StarCmd Is Here
 | 
			
		||||
 | 
			
		||||
type StarCmd struct {
 | 
			
		||||
	CMD     *exec.Cmd
 | 
			
		||||
	outfile io.ReadCloser
 | 
			
		||||
	infile  io.WriteCloser
 | 
			
		||||
	errfile io.ReadCloser
 | 
			
		||||
	running int32
 | 
			
		||||
	//Store AlL of the Standed Outputs
 | 
			
		||||
	stdout []byte
 | 
			
		||||
	//Store All of the Standed Errors
 | 
			
		||||
	errout       []byte
 | 
			
		||||
	runerr       error
 | 
			
		||||
	exitcode     int
 | 
			
		||||
	stdoutBuf    *bytes.Buffer
 | 
			
		||||
	stderrBuf    *bytes.Buffer
 | 
			
		||||
	stdoutpoint  int
 | 
			
		||||
	stderrpoint  int
 | 
			
		||||
	lock         sync.Mutex
 | 
			
		||||
	prewrite     []string
 | 
			
		||||
	prewritetime time.Duration
 | 
			
		||||
	stopctxfunc  context.CancelFunc
 | 
			
		||||
	stopctx      context.Context
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Command(command string, args ...string) (*StarCmd, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	shell := new(StarCmd)
 | 
			
		||||
	shell.running = 0
 | 
			
		||||
	shell.prewritetime = time.Millisecond * 200
 | 
			
		||||
	shell.stdoutBuf = bytes.NewBuffer(make([]byte, 0))
 | 
			
		||||
	shell.stderrBuf = bytes.NewBuffer(make([]byte, 0))
 | 
			
		||||
	shell.stopctx, shell.stopctxfunc = context.WithCancel(context.Background())
 | 
			
		||||
	cmd := exec.Command(command, args...)
 | 
			
		||||
	shell.CMD = cmd
 | 
			
		||||
	shell.infile, err = shell.CMD.StdinPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return shell, err
 | 
			
		||||
	}
 | 
			
		||||
	shell.errfile, err = shell.CMD.StderrPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return shell, err
 | 
			
		||||
	}
 | 
			
		||||
	shell.outfile, err = shell.CMD.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return shell, err
 | 
			
		||||
	}
 | 
			
		||||
	shell.runerr = nil
 | 
			
		||||
	shell.exitcode = -999
 | 
			
		||||
	return shell, nil
 | 
			
		||||
}
 | 
			
		||||
func CommandContext(ctx context.Context, command string, args ...string) (*StarCmd, error) {
 | 
			
		||||
	var err error
 | 
			
		||||
	shell := new(StarCmd)
 | 
			
		||||
	shell.running = 0
 | 
			
		||||
	shell.stdoutBuf = bytes.NewBuffer(make([]byte, 0))
 | 
			
		||||
	shell.stderrBuf = bytes.NewBuffer(make([]byte, 0))
 | 
			
		||||
	shell.prewritetime = time.Millisecond * 200
 | 
			
		||||
	shell.stopctx, shell.stopctxfunc = context.WithCancel(context.Background())
 | 
			
		||||
	cmd := exec.CommandContext(ctx, command, args...)
 | 
			
		||||
	shell.CMD = cmd
 | 
			
		||||
	shell.infile, err = shell.CMD.StdinPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return shell, err
 | 
			
		||||
	}
 | 
			
		||||
	shell.errfile, err = shell.CMD.StderrPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return shell, err
 | 
			
		||||
	}
 | 
			
		||||
	shell.outfile, err = shell.CMD.StdoutPipe()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return shell, err
 | 
			
		||||
	}
 | 
			
		||||
	shell.runerr = nil
 | 
			
		||||
	shell.exitcode = -999
 | 
			
		||||
	return shell, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) queryStdout(ctx context.Context) {
 | 
			
		||||
	for starcli.IsRunning() && starcli.CMD != nil {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-ctx.Done():
 | 
			
		||||
			return
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		out := make([]byte, 65535)
 | 
			
		||||
		n, err := starcli.outfile.Read(out)
 | 
			
		||||
		if n != 0 {
 | 
			
		||||
			starcli.lock.Lock()
 | 
			
		||||
			starcli.stdoutBuf.Write(out[:n])
 | 
			
		||||
			starcli.lock.Unlock()
 | 
			
		||||
			for _, v := range out[:n] {
 | 
			
		||||
				starcli.stdout = append(starcli.stdout, v)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err == io.EOF {
 | 
			
		||||
				break
 | 
			
		||||
			} else {
 | 
			
		||||
				if !strings.Contains(err.Error(), "file already closed") {
 | 
			
		||||
					starcli.runerr = err
 | 
			
		||||
				}
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) queryStderr(ctx context.Context) {
 | 
			
		||||
	for starcli.IsRunning() && starcli.CMD != nil {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-ctx.Done():
 | 
			
		||||
			return
 | 
			
		||||
		default:
 | 
			
		||||
		}
 | 
			
		||||
		out := make([]byte, 65535)
 | 
			
		||||
		n, err := starcli.errfile.Read(out)
 | 
			
		||||
		if n != 0 {
 | 
			
		||||
			starcli.lock.Lock()
 | 
			
		||||
			starcli.stderrBuf.Write(out[:n])
 | 
			
		||||
			starcli.lock.Unlock()
 | 
			
		||||
			for _, v := range out[:n] {
 | 
			
		||||
				starcli.errout = append(starcli.errout, v)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			if err == io.EOF {
 | 
			
		||||
				break
 | 
			
		||||
			} else {
 | 
			
		||||
				if !strings.Contains(err.Error(), "file already closed") {
 | 
			
		||||
					starcli.runerr = err
 | 
			
		||||
				}
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
func (starcli *StarCmd) NowLineOutput() (string, error) {
 | 
			
		||||
	starcli.lock.Lock()
 | 
			
		||||
	buf, _ := starcli.stdoutBuf.ReadBytes('\n')
 | 
			
		||||
	buferr, _ := starcli.stderrBuf.ReadBytes(byte('\n'))
 | 
			
		||||
	starcli.lock.Unlock()
 | 
			
		||||
	if len(buferr) != 0 {
 | 
			
		||||
		return string(buf), errors.New(string(buferr))
 | 
			
		||||
	}
 | 
			
		||||
	return string(buf), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) NowLineStdOut() string {
 | 
			
		||||
	starcli.lock.Lock()
 | 
			
		||||
	defer starcli.lock.Unlock()
 | 
			
		||||
	buf, _ := starcli.stdoutBuf.ReadBytes('\n')
 | 
			
		||||
	return string(buf)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) NowLineStdErr() error {
 | 
			
		||||
	starcli.lock.Lock()
 | 
			
		||||
	defer starcli.lock.Unlock()
 | 
			
		||||
	buferr, _ := starcli.stderrBuf.ReadBytes(byte('\n'))
 | 
			
		||||
	if len(buferr) != 0 {
 | 
			
		||||
		return errors.New(string(buferr))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) NowAllOutput() (string, error) {
 | 
			
		||||
	var outstr string
 | 
			
		||||
	starcli.lock.Lock()
 | 
			
		||||
	buf := make([]byte, starcli.stdoutBuf.Len())
 | 
			
		||||
	n, _ := starcli.stdoutBuf.Read(buf)
 | 
			
		||||
	starcli.lock.Unlock()
 | 
			
		||||
	if n != 0 {
 | 
			
		||||
		outstr = string(buf[:n])
 | 
			
		||||
	}
 | 
			
		||||
	if starcli.runerr != nil {
 | 
			
		||||
		return outstr, starcli.runerr
 | 
			
		||||
	}
 | 
			
		||||
	starcli.lock.Lock()
 | 
			
		||||
	buf = make([]byte, starcli.stderrBuf.Len())
 | 
			
		||||
	n, _ = starcli.stderrBuf.Read(buf)
 | 
			
		||||
	starcli.lock.Unlock()
 | 
			
		||||
	if n != 0 {
 | 
			
		||||
		return outstr, errors.New(string(buf[:n]))
 | 
			
		||||
	}
 | 
			
		||||
	return outstr, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) NowStdOut() string {
 | 
			
		||||
	var outstr string
 | 
			
		||||
	starcli.lock.Lock()
 | 
			
		||||
	buf := make([]byte, starcli.stdoutBuf.Len())
 | 
			
		||||
	n, _ := starcli.stdoutBuf.Read(buf)
 | 
			
		||||
	starcli.lock.Unlock()
 | 
			
		||||
	if n != 0 {
 | 
			
		||||
		outstr = string(buf[:n])
 | 
			
		||||
	}
 | 
			
		||||
	return outstr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) NowStdErr() error {
 | 
			
		||||
	starcli.lock.Lock()
 | 
			
		||||
	buf := make([]byte, starcli.stderrBuf.Len())
 | 
			
		||||
	n, _ := starcli.stderrBuf.Read(buf)
 | 
			
		||||
	starcli.lock.Unlock()
 | 
			
		||||
	if n != 0 {
 | 
			
		||||
		return errors.New(string(buf[:n]))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) AllOutPut() (string, error) {
 | 
			
		||||
	err := starcli.runerr
 | 
			
		||||
	if err == nil && len(starcli.errout) != 0 {
 | 
			
		||||
		err = errors.New(string(starcli.errout))
 | 
			
		||||
	}
 | 
			
		||||
	return string(starcli.stdout), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) AllStdOut() string {
 | 
			
		||||
	return string(starcli.stdout)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) AllStdErr() error {
 | 
			
		||||
	err := starcli.runerr
 | 
			
		||||
	if err == nil && len(starcli.errout) != 0 {
 | 
			
		||||
		err = errors.New(string(starcli.errout))
 | 
			
		||||
	}
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) setRunning(alive bool) {
 | 
			
		||||
	if alive {
 | 
			
		||||
		val := atomic.LoadInt32(&starcli.running)
 | 
			
		||||
		if val == 0 {
 | 
			
		||||
			atomic.AddInt32(&starcli.running, 1)
 | 
			
		||||
		} else {
 | 
			
		||||
			atomic.AddInt32(&starcli.running, 1-val)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	val := atomic.LoadInt32(&starcli.running)
 | 
			
		||||
	if val == 1 {
 | 
			
		||||
		atomic.AddInt32(&starcli.running, -1)
 | 
			
		||||
	} else {
 | 
			
		||||
		atomic.AddInt32(&starcli.running, -val)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func (starcli *StarCmd) Start() error {
 | 
			
		||||
	if err := starcli.CMD.Start(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	starcli.setRunning(true)
 | 
			
		||||
	go func() {
 | 
			
		||||
		err := starcli.CMD.Wait()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			starcli.runerr = err
 | 
			
		||||
		}
 | 
			
		||||
		starcli.stopctxfunc()
 | 
			
		||||
		starcli.setRunning(false)
 | 
			
		||||
		if starcli.CMD.ProcessState != nil {
 | 
			
		||||
			starcli.exitcode = starcli.CMD.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
	go starcli.queryStdout(starcli.stopctx)
 | 
			
		||||
	go starcli.queryStderr(starcli.stopctx)
 | 
			
		||||
	go func(ctx context.Context) {
 | 
			
		||||
		if len(starcli.prewrite) != 0 {
 | 
			
		||||
			for _, v := range starcli.prewrite {
 | 
			
		||||
				select {
 | 
			
		||||
				case <-ctx.Done():
 | 
			
		||||
					return
 | 
			
		||||
				default:
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				starcli.WriteCmd(v)
 | 
			
		||||
				time.Sleep(starcli.prewritetime)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}(starcli.stopctx)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) IsRunning() bool {
 | 
			
		||||
	return 0 != atomic.LoadInt32(&starcli.running)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) Stoped() <-chan struct{} {
 | 
			
		||||
	return starcli.stopctx.Done()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) Exec(cmd string, wait int) (string, error) {
 | 
			
		||||
	starcli.infile.Write([]byte(cmd + "\n"))
 | 
			
		||||
	time.Sleep(time.Millisecond * time.Duration(wait))
 | 
			
		||||
	return starcli.NowAllOutput()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) WriteCmd(cmdstr string) {
 | 
			
		||||
	starcli.infile.Write([]byte(cmdstr + "\n"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) PreWrite(cmd ...string) {
 | 
			
		||||
	for _, v := range cmd {
 | 
			
		||||
		starcli.prewrite = append(starcli.prewrite, v)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) PreWriteInterval(dt time.Duration) {
 | 
			
		||||
	starcli.prewritetime = dt
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) ExitCode() int {
 | 
			
		||||
	return starcli.exitcode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) Kill() error {
 | 
			
		||||
	err := starcli.CMD.Process.Kill()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	starcli.setRunning(false)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) GetPid() int {
 | 
			
		||||
	return starcli.CMD.Process.Pid
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) Signal(sig os.Signal) error {
 | 
			
		||||
	return starcli.CMD.Process.Signal(sig)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										348
									
								
								vendor/b612.me/staros/process_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								vendor/b612.me/staros/process_unix.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,348 @@
 | 
			
		||||
// +build linux darwin
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
//FindProcessByName 通过进程名来查询应用信息
 | 
			
		||||
func FindProcessByName(name string) (datas []Process, err error) {
 | 
			
		||||
	return FindProcess(func(in Process) bool {
 | 
			
		||||
		if name == in.Name {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
		return false
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindProcess 通过进程信息来查询应用信息
 | 
			
		||||
func FindProcess(compare func(Process) bool) (datas []Process, err error) {
 | 
			
		||||
	var name, main string
 | 
			
		||||
	var mainb []byte
 | 
			
		||||
	var netErr error
 | 
			
		||||
	var netInfo []NetConn
 | 
			
		||||
	paths, err := ioutil.ReadDir("/proc")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	netInfo, netErr = NetConnections(false, "")
 | 
			
		||||
	appendNetInfo := func(p *Process) {
 | 
			
		||||
		if netErr != nil {
 | 
			
		||||
			p.netErr = netErr
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		fds, err := ioutil.ReadDir("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd")
 | 
			
		||||
		if err != nil && Exists("/proc/"+strconv.Itoa(int(p.Pid))+"/fd") {
 | 
			
		||||
			p.netErr = err
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		for _, fd := range fds {
 | 
			
		||||
			socket, err := os.Readlink("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd/" + fd.Name())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				p.netErr = err
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			start := strings.Index(socket, "[")
 | 
			
		||||
			if start < 0 {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			sid := socket[start+1 : len(socket)-1]
 | 
			
		||||
			for _, v := range netInfo {
 | 
			
		||||
				if v.Inode == sid {
 | 
			
		||||
					v.Pid = p.Pid
 | 
			
		||||
					v.Process = p
 | 
			
		||||
					p.netConn = append(p.netConn, v)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range paths {
 | 
			
		||||
		if v.IsDir() && Exists("/proc/"+v.Name()+"/comm") {
 | 
			
		||||
			name, err = readAsString("/proc/" + v.Name() + "/comm")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			var tmp Process
 | 
			
		||||
			tmp.LocalPath, err = os.Readlink("/proc/" + v.Name() + "/exe")
 | 
			
		||||
			tmp.Path = tmp.LocalPath
 | 
			
		||||
			tmp.LocalPath = filepath.Dir(tmp.LocalPath)
 | 
			
		||||
			tmp.ExecPath, err = os.Readlink("/proc/" + v.Name() + "/cwd")
 | 
			
		||||
			tmp.Name = strings.TrimSpace(name)
 | 
			
		||||
			main, err = readAsString("/proc/" + v.Name() + "/status")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				tmp.Err = err
 | 
			
		||||
				if compare(tmp) {
 | 
			
		||||
					appendNetInfo(&tmp)
 | 
			
		||||
					datas = append(datas, tmp)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				data := splitBy(main, ":")
 | 
			
		||||
				tmp.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64)
 | 
			
		||||
				tmp.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64)
 | 
			
		||||
				tmp.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64)
 | 
			
		||||
				uids := splitBySpace(data["Uid"])
 | 
			
		||||
				gids := splitBySpace(data["Gid"])
 | 
			
		||||
				tmp.RUID, _ = strconv.Atoi(uids[0])
 | 
			
		||||
				tmp.EUID, _ = strconv.Atoi(uids[1])
 | 
			
		||||
				tmp.RGID, _ = strconv.Atoi(gids[0])
 | 
			
		||||
				tmp.EGID, _ = strconv.Atoi(gids[1])
 | 
			
		||||
				tmp.VmPeak, _ = strconv.ParseInt(splitBySpace(data["VmPeak"])[0], 10, 64)
 | 
			
		||||
				tmp.VmSize, _ = strconv.ParseInt(splitBySpace(data["VmSize"])[0], 10, 64)
 | 
			
		||||
				tmp.VmHWM, _ = strconv.ParseInt(splitBySpace(data["VmHWM"])[0], 10, 64)
 | 
			
		||||
				tmp.VmRSS, _ = strconv.ParseInt(splitBySpace(data["VmRSS"])[0], 10, 64)
 | 
			
		||||
				tmp.VmLck, _ = strconv.ParseInt(splitBySpace(data["VmLck"])[0], 10, 64)
 | 
			
		||||
				tmp.VmData, _ = strconv.ParseInt(splitBySpace(data["VmData"])[0], 10, 64)
 | 
			
		||||
				tmp.VmLck *= 1024
 | 
			
		||||
				tmp.VmData *= 1024
 | 
			
		||||
				tmp.VmPeak *= 1024
 | 
			
		||||
				tmp.VmSize *= 1024
 | 
			
		||||
				tmp.VmHWM *= 1024
 | 
			
		||||
				tmp.VmRSS *= 1024
 | 
			
		||||
			}
 | 
			
		||||
			mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/cmdline")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				tmp.Err = err
 | 
			
		||||
				if compare(tmp) {
 | 
			
		||||
					appendNetInfo(&tmp)
 | 
			
		||||
					datas = append(datas, tmp)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				args := bytes.Split(mainb, []byte{0})
 | 
			
		||||
				for _, v := range args {
 | 
			
		||||
					tmp.Args = append(tmp.Args, string(v))
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			mainb, err = ioutil.ReadFile("/proc/" + v.Name() + "/environ")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				tmp.Err = err
 | 
			
		||||
				if compare(tmp) {
 | 
			
		||||
					appendNetInfo(&tmp)
 | 
			
		||||
					datas = append(datas, tmp)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				args := bytes.Split(mainb, []byte{0})
 | 
			
		||||
				for _, v := range args {
 | 
			
		||||
					tmp.Env = append(tmp.Env, string(v))
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			main, err = readAsString("/proc/" + v.Name() + "/stat")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				tmp.Err = err
 | 
			
		||||
				if compare(tmp) {
 | 
			
		||||
					appendNetInfo(&tmp)
 | 
			
		||||
					datas = append(datas, tmp)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				times := splitBySpace(main)
 | 
			
		||||
				uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64)
 | 
			
		||||
				tmp.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000))
 | 
			
		||||
			}
 | 
			
		||||
			if compare(tmp) {
 | 
			
		||||
				appendNetInfo(&tmp)
 | 
			
		||||
				datas = append(datas, tmp)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindProcessByPid 通过Pid来查询应用信息
 | 
			
		||||
func FindProcessByPid(pid int64) (datas Process, err error) {
 | 
			
		||||
	var name, main string
 | 
			
		||||
	var mainb []byte
 | 
			
		||||
	if !Exists("/proc/" + fmt.Sprint(pid) + "/comm") {
 | 
			
		||||
		err = errors.New("Not Found")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	netInfo, netErr := NetConnections(false, "")
 | 
			
		||||
	appendNetInfo := func(p *Process) {
 | 
			
		||||
		if netErr != nil {
 | 
			
		||||
			p.netErr = netErr
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		fds, err := ioutil.ReadDir("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd")
 | 
			
		||||
		if err != nil && Exists("/proc/"+strconv.Itoa(int(p.Pid))+"/fd") {
 | 
			
		||||
			p.netErr = err
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		for _, fd := range fds {
 | 
			
		||||
			socket, err := os.Readlink("/proc/" + strconv.Itoa(int(p.Pid)) + "/fd/" + fd.Name())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				p.netErr = err
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			start := strings.Index(socket, "[")
 | 
			
		||||
			if start < 0 {
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			sid := socket[start+1 : len(socket)-1]
 | 
			
		||||
			for _, v := range netInfo {
 | 
			
		||||
				if v.Inode == sid {
 | 
			
		||||
					v.Pid = p.Pid
 | 
			
		||||
					v.Process = p
 | 
			
		||||
					p.netConn = append(p.netConn, v)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	name, err = readAsString("/proc/" + fmt.Sprint(pid) + "/comm")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/status")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	data := splitBy(main, ":")
 | 
			
		||||
	datas.Name = strings.TrimSpace(name)
 | 
			
		||||
	datas.Pid, _ = strconv.ParseInt(data["Pid"], 10, 64)
 | 
			
		||||
	datas.PPid, _ = strconv.ParseInt(data["PPid"], 10, 64)
 | 
			
		||||
	datas.TPid, _ = strconv.ParseInt(data["TracerPid"], 10, 64)
 | 
			
		||||
	uids := splitBySpace(data["Uid"])
 | 
			
		||||
	gids := splitBySpace(data["Gid"])
 | 
			
		||||
	datas.RUID, _ = strconv.Atoi(uids[0])
 | 
			
		||||
	datas.EUID, _ = strconv.Atoi(uids[1])
 | 
			
		||||
	datas.RGID, _ = strconv.Atoi(gids[0])
 | 
			
		||||
	datas.EGID, _ = strconv.Atoi(gids[1])
 | 
			
		||||
	datas.VmPeak, _ = strconv.ParseInt(splitBySpace(data["VmPeak"])[0], 10, 64)
 | 
			
		||||
	datas.VmSize, _ = strconv.ParseInt(splitBySpace(data["VmSize"])[0], 10, 64)
 | 
			
		||||
	datas.VmHWM, _ = strconv.ParseInt(splitBySpace(data["VmHWM"])[0], 10, 64)
 | 
			
		||||
	datas.VmRSS, _ = strconv.ParseInt(splitBySpace(data["VmRSS"])[0], 10, 64)
 | 
			
		||||
	datas.VmLck, _ = strconv.ParseInt(splitBySpace(data["VmLck"])[0], 10, 64)
 | 
			
		||||
	datas.VmData, _ = strconv.ParseInt(splitBySpace(data["VmData"])[0], 10, 64)
 | 
			
		||||
	datas.VmLck *= 1024
 | 
			
		||||
	datas.VmData *= 1024
 | 
			
		||||
	datas.VmPeak *= 1024
 | 
			
		||||
	datas.VmSize *= 1024
 | 
			
		||||
	datas.VmHWM *= 1024
 | 
			
		||||
	datas.VmRSS *= 1024
 | 
			
		||||
	appendNetInfo(&datas)
 | 
			
		||||
	mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/cmdline")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		datas.Err = err
 | 
			
		||||
		err = nil
 | 
			
		||||
	} else {
 | 
			
		||||
		args := bytes.Split(mainb, []byte{0})
 | 
			
		||||
		for _, v := range args {
 | 
			
		||||
			datas.Args = append(datas.Args, string(v))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mainb, err = ioutil.ReadFile("/proc/" + fmt.Sprint(pid) + "/environ")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		datas.Err = err
 | 
			
		||||
		err = nil
 | 
			
		||||
	} else {
 | 
			
		||||
		args := bytes.Split(mainb, []byte{0})
 | 
			
		||||
		for _, v := range args {
 | 
			
		||||
			datas.Env = append(datas.Env, string(v))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	datas.LocalPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/exe")
 | 
			
		||||
	datas.Path = datas.LocalPath
 | 
			
		||||
	datas.LocalPath = filepath.Dir(datas.LocalPath)
 | 
			
		||||
	datas.ExecPath, err = os.Readlink("/proc/" + fmt.Sprint(pid) + "/cwd")
 | 
			
		||||
	main, err = readAsString("/proc/" + fmt.Sprint(pid) + "/stat")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	times := splitBySpace(main)
 | 
			
		||||
	uptime, _ := strconv.ParseInt(strings.TrimSpace(times[21]), 10, 64)
 | 
			
		||||
	datas.Uptime = time.Unix(StartTime().Unix()+uptime/100, int64((float64(uptime)/100-float64(uptime/100))*1000000000))
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Daemon(path string, args ...string) (int, error) {
 | 
			
		||||
	cmd := exec.Command(path, args...)
 | 
			
		||||
	cmd.SysProcAttr = &syscall.SysProcAttr{
 | 
			
		||||
		Setsid: true,
 | 
			
		||||
	}
 | 
			
		||||
	if err := cmd.Start(); err != nil {
 | 
			
		||||
		return -1, err
 | 
			
		||||
	}
 | 
			
		||||
	pid := cmd.Process.Pid
 | 
			
		||||
	err := cmd.Process.Release()
 | 
			
		||||
	return pid, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DaemonWithUser(uid, gid uint32, groups []uint32, path string, args ...string) (int, error) {
 | 
			
		||||
	cmd := exec.Command(path, args...)
 | 
			
		||||
	cmd.SysProcAttr = &syscall.SysProcAttr{
 | 
			
		||||
		Credential: &syscall.Credential{
 | 
			
		||||
			Uid:    uid,
 | 
			
		||||
			Gid:    gid,
 | 
			
		||||
			Groups: groups,
 | 
			
		||||
		},
 | 
			
		||||
		Setsid: true,
 | 
			
		||||
	}
 | 
			
		||||
	if err := cmd.Start(); err != nil {
 | 
			
		||||
		return -1, err
 | 
			
		||||
	}
 | 
			
		||||
	pid := cmd.Process.Pid
 | 
			
		||||
	err := cmd.Process.Release()
 | 
			
		||||
	return pid, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) SetRunUser(uid, gid uint32, groups []uint32) {
 | 
			
		||||
	starcli.CMD.SysProcAttr = &syscall.SysProcAttr{
 | 
			
		||||
		Credential: &syscall.Credential{
 | 
			
		||||
			Uid:    uid,
 | 
			
		||||
			Gid:    gid,
 | 
			
		||||
			Groups: groups,
 | 
			
		||||
		},
 | 
			
		||||
		Setsid: true,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) Release() error {
 | 
			
		||||
	if starcli.CMD.SysProcAttr == nil {
 | 
			
		||||
		starcli.CMD.SysProcAttr = &syscall.SysProcAttr{
 | 
			
		||||
			Setsid: true,
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if !starcli.CMD.SysProcAttr.Setsid {
 | 
			
		||||
			starcli.CMD.SysProcAttr.Setsid = true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if !starcli.IsRunning() {
 | 
			
		||||
		if err := starcli.CMD.Start(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	time.Sleep(time.Millisecond * 10)
 | 
			
		||||
	return starcli.CMD.Process.Release()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) SetKeepCaps() error {
 | 
			
		||||
	_, _, err := syscall.RawSyscall(157 /*SYS PRCTL */, 0x8 /*PR SET KEEPCAPS*/, 1, 0)
 | 
			
		||||
	if 0 != err {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func SetKeepCaps() error {
 | 
			
		||||
	_, _, err := syscall.RawSyscall(157 /*SYS PRCTL */, 0x8 /*PR SET KEEPCAPS*/, 1, 0)
 | 
			
		||||
	if 0 != err {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										72
									
								
								vendor/b612.me/staros/process_win.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								vendor/b612.me/staros/process_win.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
// +build windows
 | 
			
		||||
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os/exec"
 | 
			
		||||
	"strconv"
 | 
			
		||||
 | 
			
		||||
	"b612.me/wincmd"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// FindProcessByName 通过进程名来查询应用信息
 | 
			
		||||
func FindProcessByName(pname string) (data []Process, err error) {
 | 
			
		||||
	var lists []map[string]string
 | 
			
		||||
	lists, err = wincmd.GetRunningProcess()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range lists {
 | 
			
		||||
		if v["name"] == pname {
 | 
			
		||||
			var tmp Process
 | 
			
		||||
			tmp.Name = pname
 | 
			
		||||
			tmp.Pid, _ = strconv.ParseInt(v["pid"], 10, 64)
 | 
			
		||||
			tmp.PPid, _ = strconv.ParseInt(v["ppid"], 10, 64)
 | 
			
		||||
			data = append(data, tmp)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FindProcessByPid 通过pid来查询应用信息
 | 
			
		||||
func FindProcessByPid(pid int64) (data Process, err error) {
 | 
			
		||||
	var lists []map[string]string
 | 
			
		||||
	lists, err = wincmd.GetRunningProcess()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range lists {
 | 
			
		||||
		if v["pid"] == fmt.Sprint(pid) {
 | 
			
		||||
			data.Name = v["name"]
 | 
			
		||||
			data.Pid = pid
 | 
			
		||||
			data.PPid, _ = strconv.ParseInt(v["ppid"], 10, 64)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	err = errors.New("Not Found")
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Daemon(path string, args ...string) (int, error) {
 | 
			
		||||
	cmd := exec.Command(path, args...)
 | 
			
		||||
	if err := cmd.Start(); err != nil {
 | 
			
		||||
		return -1, err
 | 
			
		||||
	}
 | 
			
		||||
	pid := cmd.Process.Pid
 | 
			
		||||
	cmd.Process.Release()
 | 
			
		||||
	return pid, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) SetRunUser(uid, gid uint32, groups []uint32) {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (starcli *StarCmd) Release() error {
 | 
			
		||||
	if err := starcli.CMD.Start(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	starcli.CMD.Process.Release()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/b612.me/staros/staros.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/b612.me/staros/staros.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
package staros
 | 
			
		||||
							
								
								
									
										159
									
								
								vendor/b612.me/staros/tools.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								vendor/b612.me/staros/tools.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,159 @@
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func splitBy(data, sep string) map[string]string {
 | 
			
		||||
	res := make(map[string]string)
 | 
			
		||||
	lists := strings.Split(data, "\n")
 | 
			
		||||
	for _, v := range lists {
 | 
			
		||||
		list := strings.SplitN(v, sep, 2)
 | 
			
		||||
		if len(list) != 2 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		res[strings.TrimSpace(list[0])] = strings.TrimSpace(list[1])
 | 
			
		||||
	}
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 横向替换ASCII<9>
 | 
			
		||||
func ReplaceByte9(data string) string {
 | 
			
		||||
	return string(bytes.ReplaceAll([]byte(data), []byte{9}, []byte(" ")))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func splitBySpace(data string) []string {
 | 
			
		||||
	data = string(bytes.ReplaceAll([]byte(data), []byte{9}, []byte(" ")))
 | 
			
		||||
	nomorespace := func(data string) string {
 | 
			
		||||
		return strings.ReplaceAll(data, "  ", " ")
 | 
			
		||||
	}
 | 
			
		||||
	for strings.Index(data, "  ") >= 0 {
 | 
			
		||||
		data = nomorespace(data)
 | 
			
		||||
	}
 | 
			
		||||
	return strings.Split(data, " ")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readAsString(path string) (string, error) {
 | 
			
		||||
	data, err := ioutil.ReadFile(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return string(data), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func remainOne(data, old, new string) string {
 | 
			
		||||
	data = strings.TrimSpace(data)
 | 
			
		||||
	if !strings.Contains(data, old) {
 | 
			
		||||
		return data
 | 
			
		||||
	}
 | 
			
		||||
	data = strings.ReplaceAll(data, old, new)
 | 
			
		||||
	return remainOne(data, old, new)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseHexIpPort(str string) (string, int, error) {
 | 
			
		||||
	str = strings.TrimSpace(str)
 | 
			
		||||
	if len(str) != 13 && len(str) != 37 {
 | 
			
		||||
		return "", 0, errors.New("Not a valid ip:port addr:" + str)
 | 
			
		||||
	}
 | 
			
		||||
	ipPort := strings.Split(str, ":")
 | 
			
		||||
	if len(ipPort) != 2 {
 | 
			
		||||
		return "", 0, errors.New("Not a valid ip:port addr:" + str)
 | 
			
		||||
	}
 | 
			
		||||
	if len(ipPort[0]) == 8 {
 | 
			
		||||
		ip, err := parseHexIPv4(ipPort[0])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", 0, err
 | 
			
		||||
		}
 | 
			
		||||
		port, err := parseHexPort(ipPort[1])
 | 
			
		||||
		return ip, port, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(ipPort[0]) == 32 {
 | 
			
		||||
		ip, err := parseHexIPv6(ipPort[0])
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", 0, err
 | 
			
		||||
		}
 | 
			
		||||
		port, err := parseHexPort(ipPort[1])
 | 
			
		||||
		return ip, port, err
 | 
			
		||||
	}
 | 
			
		||||
	return "", 0, errors.New("Invalid ip address:" + str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseHexPort(str string) (int, error) {
 | 
			
		||||
	tmpUint32, err := strconv.ParseUint(str, 16, 32)
 | 
			
		||||
	return int(tmpUint32), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseHexIPv4(str string) (string, error) {
 | 
			
		||||
	var result string
 | 
			
		||||
	if len(str) != 8 {
 | 
			
		||||
		return "", errors.New("Not a vaild ipv4:" + str)
 | 
			
		||||
	}
 | 
			
		||||
	tmpUint64, err := strconv.ParseUint(str, 16, 32)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	numicIp := uint32(tmpUint64)
 | 
			
		||||
	for i := 0; i < 4; i++ {
 | 
			
		||||
		result += strconv.FormatUint(uint64(uint8(numicIp>>(8*uint8(i)))), 10) + "."
 | 
			
		||||
	}
 | 
			
		||||
	return result[0 : len(result)-1], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseHexIPv6(str string) (string, error) {
 | 
			
		||||
	var result string
 | 
			
		||||
	if len(str) != 32 {
 | 
			
		||||
		return "", errors.New("Not a vaild ipv6:" + str)
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < 4; i++ {
 | 
			
		||||
		part := str[i*8 : (i+1)*8]
 | 
			
		||||
		tmpUint64, err := strconv.ParseUint(part, 16, 32)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
		tmpUint32 := uint32(tmpUint64)
 | 
			
		||||
		//07C2022A
 | 
			
		||||
		for i := 0; i < 4; i++ {
 | 
			
		||||
			tmp := strconv.FormatUint(uint64(uint8(tmpUint32>>uint8(8*i))), 16)
 | 
			
		||||
			if len(tmp) == 1 {
 | 
			
		||||
				tmp = "0" + tmp
 | 
			
		||||
			}
 | 
			
		||||
			result += tmp
 | 
			
		||||
			if (i+1)%2 == 0 {
 | 
			
		||||
				result += ":"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	ipv6 := result[0 : len(result)-1]
 | 
			
		||||
	ipv6List := strings.Split(ipv6, ":")
 | 
			
		||||
	prepareZero := false
 | 
			
		||||
	alreadyZero := false
 | 
			
		||||
	for k, v := range ipv6List {
 | 
			
		||||
		if v == "0000" && !alreadyZero {
 | 
			
		||||
			ipv6List[k] = ""
 | 
			
		||||
			prepareZero = true
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if v != "0000" && prepareZero {
 | 
			
		||||
			alreadyZero = true
 | 
			
		||||
		}
 | 
			
		||||
		var nonZero = 0
 | 
			
		||||
		for i := 0; i < 4; i++ {
 | 
			
		||||
			sig := v[i : i+1]
 | 
			
		||||
			if sig != "0" {
 | 
			
		||||
				nonZero = i
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		ipv6List[k] = v[nonZero:4]
 | 
			
		||||
	}
 | 
			
		||||
	ipv6 = strings.TrimSuffix(remainOne(strings.Join(ipv6List, ":"), ":::", "::"), "::")
 | 
			
		||||
	if ipv6 == "" {
 | 
			
		||||
		ipv6 = "::0"
 | 
			
		||||
	}
 | 
			
		||||
	return ipv6, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										114
									
								
								vendor/b612.me/staros/typed.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								vendor/b612.me/staros/typed.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
			
		||||
package staros
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	KB = 1024
 | 
			
		||||
	MB = KB << 10
 | 
			
		||||
	GB = MB << 10
 | 
			
		||||
	TB = GB << 10
 | 
			
		||||
	PB = TB << 10
 | 
			
		||||
)
 | 
			
		||||
const (
 | 
			
		||||
	TCP_UNKNOWN = iota
 | 
			
		||||
	TCP_ESTABLISHED
 | 
			
		||||
	TCP_SYN_SENT
 | 
			
		||||
	TCP_SYN_RECV
 | 
			
		||||
	TCP_FIN_WAIT1
 | 
			
		||||
	TCP_FIN_WAIT2
 | 
			
		||||
	TCP_TIME_WAIT
 | 
			
		||||
	TCP_CLOSE
 | 
			
		||||
	TCP_CLOSE_WAIT
 | 
			
		||||
	TCP_LAST_ACL
 | 
			
		||||
	TCP_LISTEN
 | 
			
		||||
	TCP_CLOSING
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var TCP_STATE = []string{"TCP_UNKNOWN", "TCP_ESTABLISHED", "TCP_SYN_SENT", "TCP_SYN_RECV", "TCP_FIN_WAIT1", "TCP_FIN_WAIT2", "TCP_TIME_WAIT", "TCP_CLOSE", "TCP_CLOSE_WAIT", "TCP_LAST_ACL", "TCP_LISTEN", "TCP_CLOSING"}
 | 
			
		||||
 | 
			
		||||
type NetAdapter struct {
 | 
			
		||||
	Name      string
 | 
			
		||||
	RecvBytes uint64
 | 
			
		||||
	SendBytes uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NetSpeed struct {
 | 
			
		||||
	Name      string
 | 
			
		||||
	RecvBytes float64
 | 
			
		||||
	SendBytes float64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Process 定义一个进程的信息
 | 
			
		||||
type Process struct {
 | 
			
		||||
	PPid      int64
 | 
			
		||||
	Pid       int64
 | 
			
		||||
	Name      string
 | 
			
		||||
	ExecPath  string
 | 
			
		||||
	LocalPath string
 | 
			
		||||
	Path      string
 | 
			
		||||
	Args      []string
 | 
			
		||||
	Env       []string
 | 
			
		||||
	RUID      int
 | 
			
		||||
	EUID      int
 | 
			
		||||
	RGID      int
 | 
			
		||||
	EGID      int
 | 
			
		||||
	TPid      int64
 | 
			
		||||
	Uptime    time.Time
 | 
			
		||||
	VmPeak    int64
 | 
			
		||||
	VmSize    int64
 | 
			
		||||
	VmLck     int64
 | 
			
		||||
	VmHWM     int64
 | 
			
		||||
	VmRSS     int64
 | 
			
		||||
	VmData    int64
 | 
			
		||||
	netConn   []NetConn
 | 
			
		||||
	netErr    error
 | 
			
		||||
	Err       error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p Process) GetNetConns() ([]NetConn, error) {
 | 
			
		||||
	return p.netConn, p.netErr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MemStatus struct {
 | 
			
		||||
	All           uint64
 | 
			
		||||
	Used          uint64
 | 
			
		||||
	Free          uint64
 | 
			
		||||
	Shared        uint64
 | 
			
		||||
	BuffCache     uint64
 | 
			
		||||
	Available     uint64
 | 
			
		||||
	SwapAll       uint64
 | 
			
		||||
	SwapUsed      uint64
 | 
			
		||||
	SwapFree      uint64
 | 
			
		||||
	VirtualAll    uint64
 | 
			
		||||
	VirtualUsed   uint64
 | 
			
		||||
	VirtualAvail  uint64
 | 
			
		||||
	AvailExtended uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DiskStatus struct {
 | 
			
		||||
	All       uint64
 | 
			
		||||
	Used      uint64
 | 
			
		||||
	Free      uint64
 | 
			
		||||
	Available uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NetConn struct {
 | 
			
		||||
	LocalAddr    string
 | 
			
		||||
	LocalPort    int
 | 
			
		||||
	Typed        string
 | 
			
		||||
	RemoteAddr   string
 | 
			
		||||
	RemotePort   int
 | 
			
		||||
	Socket       string
 | 
			
		||||
	Inode        string
 | 
			
		||||
	Status       string
 | 
			
		||||
	TX_Queue     int64
 | 
			
		||||
	RX_Queue     int64
 | 
			
		||||
	TimerActive  string
 | 
			
		||||
	TimerJiffies int64
 | 
			
		||||
	RtoTimer     int64
 | 
			
		||||
	Pid          int64
 | 
			
		||||
	Uid          int64
 | 
			
		||||
	Process      *Process
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										79
									
								
								vendor/b612.me/win32api/advapi32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								vendor/b612.me/win32api/advapi32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,79 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/sys/windows"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func DuplicateTokenEx(hExistingToken HANDLE, dwDesiredAccess DWORD,
 | 
			
		||||
	lpTokenAttributes uintptr, ImpersonationLevel int,
 | 
			
		||||
	TokenType TOKEN_TYPE, phNewToken *TOKEN) error {
 | 
			
		||||
 | 
			
		||||
	advapi32, err := syscall.LoadLibrary("advapi32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Advapi32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(advapi32)
 | 
			
		||||
	Dup, err := syscall.GetProcAddress(syscall.Handle(advapi32), "DuplicateTokenEx")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load WTSQueryUserToken API")
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall6(uintptr(Dup), 6, uintptr(hExistingToken), uintptr(dwDesiredAccess), lpTokenAttributes, uintptr(ImpersonationLevel),
 | 
			
		||||
		uintptr(TokenType), uintptr(unsafe.Pointer(phNewToken)))
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CreateProcessAsUser(hToken TOKEN, lpApplicationName, lpCommandLine string,
 | 
			
		||||
	lpProcessAttributes, lpThreadAttributes, bInheritHandles uintptr,
 | 
			
		||||
	dwCreationFlags uint16, lpEnvironment HANDLE, lpCurrentDirectory string,
 | 
			
		||||
	lpStartupInfo *StartupInfo, lpProcessInformation *ProcessInformation) error {
 | 
			
		||||
	var (
 | 
			
		||||
		commandLine uintptr = 0
 | 
			
		||||
		workingDir  uintptr = 0
 | 
			
		||||
	)
 | 
			
		||||
	advapi32, err := syscall.LoadLibrary("advapi32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Advapi32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(advapi32)
 | 
			
		||||
	CPAU, err := syscall.GetProcAddress(syscall.Handle(advapi32), "CreateProcessAsUserW")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load CreateProcessAsUserW API")
 | 
			
		||||
	}
 | 
			
		||||
	if len(lpCommandLine) > 0 {
 | 
			
		||||
		commandLine = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpCommandLine)))
 | 
			
		||||
	}
 | 
			
		||||
	if len(lpCurrentDirectory) > 0 {
 | 
			
		||||
		workingDir = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpCurrentDirectory)))
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall12(uintptr(CPAU), 11, uintptr(hToken), uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(lpApplicationName))),
 | 
			
		||||
		commandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, uintptr(dwCreationFlags), uintptr(lpEnvironment),
 | 
			
		||||
		workingDir, uintptr(unsafe.Pointer(lpStartupInfo)), uintptr(unsafe.Pointer(lpProcessInformation)), 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
func GetTokenInformation(TokenHandle HANDLE, TokenInformationClass, TokenInformation,
 | 
			
		||||
	TokenInformationLength uintptr, ReturnLength *uintptr) error {
 | 
			
		||||
	advapi32, err := syscall.LoadLibrary("advapi32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Advapi32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(advapi32)
 | 
			
		||||
	GTI, err := syscall.GetProcAddress(syscall.Handle(advapi32), "GetTokenInformation")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load GetTokenInformation API")
 | 
			
		||||
	}
 | 
			
		||||
	if r, _, errno := syscall.Syscall6(uintptr(GTI), 5, uintptr(TokenHandle), TokenInformationClass,
 | 
			
		||||
		TokenInformation, TokenInformationLength, uintptr(unsafe.Pointer(ReturnLength)), 0); r == 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/b612.me/win32api/advapi32typedef.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/b612.me/win32api/advapi32typedef.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
type TOKEN_LINKED_TOKEN struct {
 | 
			
		||||
	LinkedToken TOKEN
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										284
									
								
								vendor/b612.me/win32api/kernel32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										284
									
								
								vendor/b612.me/win32api/kernel32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,284 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func WTSGetActiveConsoleSessionId() (DWORD, error) {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, errors.New("Can't Load Kernel32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	WTGet, err := syscall.GetProcAddress(syscall.Handle(kernel32), "WTSGetActiveConsoleSessionId")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, errors.New("Can't Load WTSGetActiveConsoleSessionId API")
 | 
			
		||||
	}
 | 
			
		||||
	res, _, _ := syscall.Syscall(uintptr(WTGet), 0, 0, 0, 0)
 | 
			
		||||
	return DWORD(res), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CloseHandle(hObject HANDLE) error {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Kernel32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	CH, err := syscall.GetProcAddress(syscall.Handle(kernel32), "CloseHandle")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load CloseHandle API")
 | 
			
		||||
	}
 | 
			
		||||
	if r, _, errno := syscall.Syscall(uintptr(CH), 1, uintptr(hObject), 0, 0); r == 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CreateToolhelp32Snapshot(dwFlags, th32ProcessID DWORD) (HANDLE, error) {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, errors.New("Can't Load Kernel32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	CTS, err := syscall.GetProcAddress(syscall.Handle(kernel32), "CreateToolhelp32Snapshot")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, errors.New("Can't Load CreateToolhelp32Snapshot API")
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall(uintptr(CTS), 2, uintptr(dwFlags), uintptr(th32ProcessID), 0)
 | 
			
		||||
	if int(r) == -1 {
 | 
			
		||||
		return 0, error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return HANDLE(r), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Process32Next(hSnapshot HANDLE, lppe *PROCESSENTRY32) error {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Kernel32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	PN, err := syscall.GetProcAddress(syscall.Handle(kernel32), "Process32Next")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Process32Next API")
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall(uintptr(PN), 2, uintptr(hSnapshot), uintptr(unsafe.Pointer(lppe)), 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		if errno != 0 {
 | 
			
		||||
			return error(errno)
 | 
			
		||||
		}
 | 
			
		||||
		return syscall.EINVAL
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetProcessId(Process HANDLE) uint32 {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	GPI, err := syscall.GetProcAddress(syscall.Handle(kernel32), "GetProcessId")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	r, _, _ := syscall.Syscall(uintptr(GPI), 1, uintptr(Process), 0, 0)
 | 
			
		||||
	return uint32(r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetTickCount() (uint32, error) {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	GTC, err := syscall.GetProcAddress(syscall.Handle(kernel32), "GetTickCount")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	r, _, _ := syscall.Syscall(uintptr(GTC), 0, 0, 0, 0)
 | 
			
		||||
	return uint32(r), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GlobalMemoryStatusEx(data *MEMORYSTATUSEX) (bool, error) {
 | 
			
		||||
	(*data).DwLength = DWORD(unsafe.Sizeof(*data))
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	GMS, err := syscall.GetProcAddress(syscall.Handle(kernel32), "GlobalMemoryStatusEx")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall(uintptr(GMS), 1, uintptr(unsafe.Pointer(data)), 0, 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		if errno != 0 {
 | 
			
		||||
			return false, error(errno)
 | 
			
		||||
		}
 | 
			
		||||
		return false, syscall.EINVAL
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func LockFileEx(hFile HANDLE, dwFlags DWORD, dwReserved DWORD, nNumberOfBytesToLockLow DWORD,
 | 
			
		||||
	nNumberOfBytesToLockHigh DWORD, lpOverlapped *syscall.Overlapped) (bool, error) {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	Lck, err := syscall.GetProcAddress(syscall.Handle(kernel32), "LockFileEx")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall6(uintptr(Lck), 6, uintptr(hFile), uintptr(dwFlags), uintptr(dwReserved),
 | 
			
		||||
		uintptr(nNumberOfBytesToLockLow), uintptr(nNumberOfBytesToLockHigh), uintptr(unsafe.Pointer(lpOverlapped)))
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		if errno != 0 {
 | 
			
		||||
			return false, error(errno)
 | 
			
		||||
		}
 | 
			
		||||
		return false, syscall.EINVAL
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func OpenFileById(hVolumeHint HANDLE, lpFileId *FILE_ID_DESCRIPTOR, dwDesiredAccess DWORD, dwShareMode DWORD,
 | 
			
		||||
	lpSecurityAttributes *syscall.SecurityAttributes, dwFlagsAndAttributes DWORD) (HANDLE, error) {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	ofb, err := syscall.GetProcAddress(syscall.Handle(kernel32), "OpenFileById")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall6(ofb, 6, uintptr(hVolumeHint),
 | 
			
		||||
		uintptr(unsafe.Pointer(lpFileId)), uintptr(dwDesiredAccess), uintptr(dwShareMode),
 | 
			
		||||
		uintptr(unsafe.Pointer(lpSecurityAttributes)), uintptr(dwFlagsAndAttributes))
 | 
			
		||||
	if r == syscall.INVALID_FILE_ATTRIBUTES {
 | 
			
		||||
		if errno != 0 {
 | 
			
		||||
			return HANDLE(r), error(errno)
 | 
			
		||||
		}
 | 
			
		||||
		return HANDLE(r), syscall.EINVAL
 | 
			
		||||
	}
 | 
			
		||||
	return HANDLE(r), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CreateEventW(lpEventAttributes *syscall.SecurityAttributes, bManualReset bool,
 | 
			
		||||
	bInitialState bool, lpName LPCWSTR) (HANDLE, error) {
 | 
			
		||||
	var intBManualReset, intBInitialState int
 | 
			
		||||
	if bManualReset {
 | 
			
		||||
		intBManualReset = 1
 | 
			
		||||
	}
 | 
			
		||||
	if bInitialState {
 | 
			
		||||
		intBInitialState = 1
 | 
			
		||||
	}
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	Lck, err := syscall.GetProcAddress(syscall.Handle(kernel32), "CreateEventW")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall6(uintptr(Lck), 4, uintptr(unsafe.Pointer(lpEventAttributes)),
 | 
			
		||||
		uintptr(intBManualReset), uintptr(intBInitialState), uintptr(unsafe.Pointer(lpName)), 0, 0)
 | 
			
		||||
	if HANDLE(r) == 0 {
 | 
			
		||||
		if errno != 0 {
 | 
			
		||||
			return HANDLE(r), error(errno)
 | 
			
		||||
		}
 | 
			
		||||
		return HANDLE(r), syscall.EINVAL
 | 
			
		||||
	}
 | 
			
		||||
	return HANDLE(r), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetLogicalDriveStringsW(nBufferLength DWORD, lpBuffer LPWSTR) error {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	glds, err := syscall.GetProcAddress(syscall.Handle(kernel32), "GetLogicalDriveStringsW")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, _, errno := syscall.Syscall(uintptr(glds), 2, uintptr(nBufferLength), uintptr(unsafe.Pointer(lpBuffer)), 0)
 | 
			
		||||
	if errno != 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetVolumeInformationW(lpRootPathName LPCWSTR, lpVolumeNameBuffer LPWSTR, nVolumeNameSize DWORD,
 | 
			
		||||
	lpVolumeSerialNumber LPDWORD, lpMaximumComponentLength LPDWORD, lpFileSystemFlags LPDWORD,
 | 
			
		||||
	lpFileSystemNameBuffer LPWSTR, nFileSystemNameSize DWORD) error {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	glds, err := syscall.GetProcAddress(syscall.Handle(kernel32), "GetVolumeInformationW")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	_, _, errno := syscall.Syscall9(uintptr(glds), 8, uintptr(unsafe.Pointer(lpRootPathName)),
 | 
			
		||||
		uintptr(unsafe.Pointer(lpVolumeNameBuffer)), uintptr(nVolumeNameSize), uintptr(unsafe.Pointer(lpVolumeSerialNumber)),
 | 
			
		||||
		uintptr(unsafe.Pointer(lpMaximumComponentLength)), uintptr(unsafe.Pointer(lpFileSystemFlags)),
 | 
			
		||||
		uintptr(unsafe.Pointer(lpFileSystemNameBuffer)), uintptr(nFileSystemNameSize), 0)
 | 
			
		||||
	if errno != 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DeviceIoControl(hDevice HANDLE, dwIoControlCode DWORD, lpInBuffer LPVOID, nInBufferSize DWORD, lpOutBuffer LPVOID,
 | 
			
		||||
	nOutBufferSize DWORD, lpBytesReturned LPDWORD, lpOverlapped *syscall.Overlapped) (bool, error) {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	dic, err := syscall.GetProcAddress(syscall.Handle(kernel32), "DeviceIoControl")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall9(uintptr(dic), 8, uintptr(hDevice), uintptr(dwIoControlCode),
 | 
			
		||||
		uintptr(unsafe.Pointer(lpInBuffer)), uintptr(nInBufferSize), uintptr(unsafe.Pointer(lpOutBuffer)), uintptr(nOutBufferSize),
 | 
			
		||||
		uintptr(unsafe.Pointer(lpBytesReturned)), uintptr(unsafe.Pointer(lpOverlapped)), 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		if errno != 0 {
 | 
			
		||||
			return false, error(errno)
 | 
			
		||||
		} else {
 | 
			
		||||
			return false, syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DeviceIoControlPtr(hDevice HANDLE, dwIoControlCode DWORD, lpInBuffer uintptr, nInBufferSize DWORD, lpOutBuffer uintptr,
 | 
			
		||||
	nOutBufferSize DWORD, lpBytesReturned LPDWORD, lpOverlapped *syscall.Overlapped) (bool, error) {
 | 
			
		||||
	kernel32, err := syscall.LoadLibrary("kernel32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(kernel32)
 | 
			
		||||
	dic, err := syscall.GetProcAddress(syscall.Handle(kernel32), "DeviceIoControl")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall9(uintptr(dic), 8, uintptr(hDevice), uintptr(dwIoControlCode),
 | 
			
		||||
		lpInBuffer, uintptr(nInBufferSize), lpOutBuffer, uintptr(nOutBufferSize),
 | 
			
		||||
		uintptr(unsafe.Pointer(lpBytesReturned)), uintptr(unsafe.Pointer(lpOverlapped)), 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		if errno != 0 {
 | 
			
		||||
			return false, error(errno)
 | 
			
		||||
		} else {
 | 
			
		||||
			return false, syscall.EINVAL
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										115
									
								
								vendor/b612.me/win32api/kernel32typedef.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								vendor/b612.me/win32api/kernel32typedef.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,115 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
import "syscall"
 | 
			
		||||
 | 
			
		||||
type Ulong int32
 | 
			
		||||
type Ulong_ptr uintptr
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	LOCKFILE_EXCLUSIVE_LOCK   DWORD = 0x00000002
 | 
			
		||||
	LOCKFILE_FAIL_IMMEDIATELY DWORD = 0x00000001
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type PROCESSENTRY32 struct {
 | 
			
		||||
	DwSize              Ulong
 | 
			
		||||
	CntUsage            Ulong
 | 
			
		||||
	Th32ProcessID       Ulong
 | 
			
		||||
	Th32DefaultHeapID   Ulong_ptr
 | 
			
		||||
	Th32ModuleID        Ulong
 | 
			
		||||
	CntThreads          Ulong
 | 
			
		||||
	Th32ParentProcessID Ulong
 | 
			
		||||
	PcPriClassBase      Ulong
 | 
			
		||||
	DwFlags             Ulong
 | 
			
		||||
	SzExeFile           [260]byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MEMORYSTATUSEX struct {
 | 
			
		||||
	DwLength                DWORD
 | 
			
		||||
	DwMemoryLoad            DWORD
 | 
			
		||||
	UllTotalPhys            DWORDLONG
 | 
			
		||||
	UllAvailPhys            DWORDLONG
 | 
			
		||||
	UllTotalPageFile        DWORDLONG
 | 
			
		||||
	UllAvailPageFile        DWORDLONG
 | 
			
		||||
	UllTotalVirtual         DWORDLONG
 | 
			
		||||
	UllAvailVirtual         DWORDLONG
 | 
			
		||||
	UllAvailExtendedVirtual DWORDLONG
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type USN_JOURNAL_DATA struct {
 | 
			
		||||
	UsnJournalID    DWORDLONG
 | 
			
		||||
	FirstUsn        USN
 | 
			
		||||
	NextUsn         USN
 | 
			
		||||
	LowestValidUsn  USN
 | 
			
		||||
	MaxUsn          USN
 | 
			
		||||
	MaximumSize     DWORDLONG
 | 
			
		||||
	AllocationDelta DWORDLONG
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type READ_USN_JOURNAL_DATA struct {
 | 
			
		||||
	StartUsn          USN
 | 
			
		||||
	ReasonMask        DWORD
 | 
			
		||||
	ReturnOnlyOnClose DWORD
 | 
			
		||||
	Timeout           DWORDLONG
 | 
			
		||||
	BytesToWaitFor    DWORDLONG
 | 
			
		||||
	UsnJournalID      DWORDLONG
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type USN_RECORD struct {
 | 
			
		||||
	RecordLength              DWORD
 | 
			
		||||
	MajorVersion              WORD
 | 
			
		||||
	MinorVersion              WORD
 | 
			
		||||
	FileReferenceNumber       DWORDLONG
 | 
			
		||||
	ParentFileReferenceNumber DWORDLONG
 | 
			
		||||
	Usn                       USN
 | 
			
		||||
	TimeStamp                 LARGE_INTEGER
 | 
			
		||||
	Reason                    DWORD
 | 
			
		||||
	SourceInfo                DWORD
 | 
			
		||||
	SecurityId                DWORD
 | 
			
		||||
	FileAttributes            DWORD
 | 
			
		||||
	FileNameLength            WORD
 | 
			
		||||
	FileNameOffset            WORD
 | 
			
		||||
	FileName                  [1]WCHAR
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type MFT_ENUM_DATA struct {
 | 
			
		||||
	StartFileReferenceNumber DWORDLONG
 | 
			
		||||
	LowUsn                   USN
 | 
			
		||||
	HighUsn                  USN
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	FSCTL_ENUM_USN_DATA        = 0x900B3
 | 
			
		||||
	FSCTL_QUERY_USN_JOURNAL    = 0x900F4
 | 
			
		||||
	FSCTL_READ_USN_JOURNAL     = 0x900BB
 | 
			
		||||
	O_RDONLY                   = syscall.O_RDONLY
 | 
			
		||||
	O_RDWR                     = syscall.O_RDWR
 | 
			
		||||
	O_CREAT                    = syscall.O_CREAT
 | 
			
		||||
	O_WRONLY                   = syscall.O_WRONLY
 | 
			
		||||
	GENERIC_READ               = syscall.GENERIC_READ
 | 
			
		||||
	GENERIC_WRITE              = syscall.GENERIC_WRITE
 | 
			
		||||
	FILE_APPEND_DATA           = syscall.FILE_APPEND_DATA
 | 
			
		||||
	FILE_SHARE_READ            = syscall.FILE_SHARE_READ
 | 
			
		||||
	FILE_SHARE_WRITE           = syscall.FILE_SHARE_WRITE
 | 
			
		||||
	ERROR_FILE_NOT_FOUND       = syscall.ERROR_FILE_NOT_FOUND
 | 
			
		||||
	O_APPEND                   = syscall.O_APPEND
 | 
			
		||||
	O_CLOEXEC                  = syscall.O_CLOEXEC
 | 
			
		||||
	O_EXCL                     = syscall.O_EXCL
 | 
			
		||||
	O_TRUNC                    = syscall.O_TRUNC
 | 
			
		||||
	CREATE_ALWAYS              = syscall.CREATE_ALWAYS
 | 
			
		||||
	CREATE_NEW                 = syscall.CREATE_NEW
 | 
			
		||||
	OPEN_ALWAYS                = syscall.OPEN_ALWAYS
 | 
			
		||||
	TRUNCATE_EXISTING          = syscall.TRUNCATE_EXISTING
 | 
			
		||||
	OPEN_EXISTING              = syscall.OPEN_EXISTING
 | 
			
		||||
	FILE_ATTRIBUTE_NORMAL      = syscall.FILE_ATTRIBUTE_NORMAL
 | 
			
		||||
	FILE_FLAG_BACKUP_SEMANTICS = syscall.FILE_FLAG_BACKUP_SEMANTICS
 | 
			
		||||
	FILE_ATTRIBUTE_DIRECTORY   = syscall.FILE_ATTRIBUTE_DIRECTORY
 | 
			
		||||
	MAX_LONG_PATH              = syscall.MAX_LONG_PATH
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type FILE_ID_DESCRIPTOR struct {
 | 
			
		||||
	DwSize         DWORD
 | 
			
		||||
	Type           DWORD
 | 
			
		||||
	FileId         DWORDLONG
 | 
			
		||||
	ObjectId       DWORDLONG
 | 
			
		||||
	ExtendedFileId DWORDLONG
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										88
									
								
								vendor/b612.me/win32api/shell32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								vendor/b612.me/win32api/shell32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,88 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ShellExecute(hwnd HWND, lpOperation, lpFile, lpParameters, lpDirectory string, nShowCmd int) error {
 | 
			
		||||
	shell32, err := syscall.LoadLibrary("shell32.dll")
 | 
			
		||||
	var op, param, directory uintptr
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Shell32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(shell32)
 | 
			
		||||
	ShellExecute, err := syscall.GetProcAddress(syscall.Handle(shell32), "ShellExecuteW")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load ShellExecute API")
 | 
			
		||||
	}
 | 
			
		||||
	if len(lpOperation) != 0 {
 | 
			
		||||
		op = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpOperation)))
 | 
			
		||||
	}
 | 
			
		||||
	if len(lpParameters) != 0 {
 | 
			
		||||
		param = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpParameters)))
 | 
			
		||||
	}
 | 
			
		||||
	if len(lpDirectory) != 0 {
 | 
			
		||||
		directory = uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpDirectory)))
 | 
			
		||||
	}
 | 
			
		||||
	r, _, _ := syscall.Syscall6(uintptr(ShellExecute), 6,
 | 
			
		||||
		uintptr(hwnd),
 | 
			
		||||
		op,
 | 
			
		||||
		uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(lpFile))),
 | 
			
		||||
		param,
 | 
			
		||||
		directory,
 | 
			
		||||
		uintptr(nShowCmd))
 | 
			
		||||
	if r < 32 {
 | 
			
		||||
		return errors.New("ERROR:" + strconv.Itoa(int(r)))
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
func ShellExecuteEX2(hwnd HWND, lpVerb, lpFile, lpParameters, lpDirectory string, nShow int) error {
 | 
			
		||||
	var newcmd SHELLEXECUTEINFOW
 | 
			
		||||
	newcmd.cbSize = DWORD(unsafe.Sizeof(newcmd))
 | 
			
		||||
	newcmd.hwnd = hwnd
 | 
			
		||||
	newcmd.lpVerb = lpVerb
 | 
			
		||||
	newcmd.lpFile = lpFile
 | 
			
		||||
	newcmd.lpParameters = lpParameters
 | 
			
		||||
	newcmd.lpDirectory = lpDirectory
 | 
			
		||||
	newcmd.nShow = nShow
 | 
			
		||||
	shell32, err := syscall.LoadLibrary("shell32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Shell32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(shell32)
 | 
			
		||||
	ShellExecuteEx, err := syscall.GetProcAddress(syscall.Handle(shell32), "ShellExecuteExW")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load ShellExecuteEx API")
 | 
			
		||||
	}
 | 
			
		||||
	r, _, _ := syscall.Syscall6(ShellExecuteEx, 1, uintptr(unsafe.Pointer(&newcmd)), 0, 0, 0, 0, 0)
 | 
			
		||||
	fmt.Println(strconv.Itoa(int(r)))
 | 
			
		||||
	fmt.Println(strconv.Itoa(int(newcmd.hInstApp)))
 | 
			
		||||
	if r != 0 {
 | 
			
		||||
		return errors.New("Error Recured")
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
func ShellExecuteEx(muzika *SHELLEXECUTEINFOW) error {
 | 
			
		||||
	shell32, err := syscall.LoadLibrary("shell32.dll")
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Shell32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(shell32)
 | 
			
		||||
	ShellExecuteEx, err := syscall.GetProcAddress(syscall.Handle(shell32), "ShellExecuteExW")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load ShellExecuteEx API")
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall6(ShellExecuteEx, 1, uintptr(unsafe.Pointer(muzika)), 0, 0, 0, 0, 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								vendor/b612.me/win32api/shell32typedef.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								vendor/b612.me/win32api/shell32typedef.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
type SHELLEXECUTEINFOW struct {
 | 
			
		||||
	CbSize          DWORD
 | 
			
		||||
	FMask           ULONG
 | 
			
		||||
	Hwnd            HWND
 | 
			
		||||
	LpVerb          uintptr
 | 
			
		||||
	LpFile          uintptr
 | 
			
		||||
	LpParameters    uintptr
 | 
			
		||||
	LpDirectory     uintptr
 | 
			
		||||
	NShow           int
 | 
			
		||||
	HInstApp        HINSTANCE
 | 
			
		||||
	LpIDList        LPVOID
 | 
			
		||||
	LpClass         uintptr
 | 
			
		||||
	HkeyClass       HKEY
 | 
			
		||||
	DwHotKey        DWORD
 | 
			
		||||
	UnionorHMonitor HANDLE
 | 
			
		||||
	HProcess        HANDLE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type UNION struct {
 | 
			
		||||
	HIcon    HANDLE
 | 
			
		||||
	HMonitor HANDLE
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										49
									
								
								vendor/b612.me/win32api/user32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/b612.me/win32api/user32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func Keybd_event(keyname string, keydown bool) error {
 | 
			
		||||
	var key int
 | 
			
		||||
	var down uintptr
 | 
			
		||||
	if !keydown {
 | 
			
		||||
		down = KEYEVENTF_KEYUP
 | 
			
		||||
	}
 | 
			
		||||
	switch keyname {
 | 
			
		||||
	case "shift":
 | 
			
		||||
		key = VK_SHIFT
 | 
			
		||||
	case "lshift":
 | 
			
		||||
		key = VK_LSHIFT
 | 
			
		||||
	case "rshift":
 | 
			
		||||
		key = VK_RSHIFT
 | 
			
		||||
	case "a":
 | 
			
		||||
		key = VK_A
 | 
			
		||||
	}
 | 
			
		||||
	user32, err := syscall.LoadLibrary("user32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load User32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(user32)
 | 
			
		||||
	keyevent, err := syscall.GetProcAddress(syscall.Handle(user32), "keybd_event")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Keybd_event API")
 | 
			
		||||
	}
 | 
			
		||||
	syscall.Syscall6(keyevent, 4, uintptr(key), uintptr(key), down, 0, 0, 0)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Keybd_event_origin(key, keyenv, down, extra uintptr) error {
 | 
			
		||||
	user32, err := syscall.LoadLibrary("user32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load User32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(user32)
 | 
			
		||||
	keyevent, err := syscall.GetProcAddress(syscall.Handle(user32), "keybd_event")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Keybd_event API")
 | 
			
		||||
	}
 | 
			
		||||
	syscall.Syscall6(keyevent, 4, key, keyenv, down, extra, 0, 0)
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										180
									
								
								vendor/b612.me/win32api/user32_typedef.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								vendor/b612.me/win32api/user32_typedef.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,180 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	VK_SHIFT        = 0x10
 | 
			
		||||
	VK_CTRL         = 0x11
 | 
			
		||||
	VK_ALT          = 0x12
 | 
			
		||||
	VK_LSHIFT       = 0xA0
 | 
			
		||||
	VK_RSHIFT       = 0xA1
 | 
			
		||||
	VK_LCONTROL     = 0xA2
 | 
			
		||||
	VK_RCONTROL     = 0xA3
 | 
			
		||||
	KEYEVENTF_KEYUP = 0x0002
 | 
			
		||||
)
 | 
			
		||||
const (
 | 
			
		||||
	VK_LBUTTON             = 0x01
 | 
			
		||||
	VK_RBUTTON             = 0x02
 | 
			
		||||
	VK_CANCEL              = 0x03
 | 
			
		||||
	VK_MBUTTON             = 0x04
 | 
			
		||||
	VK_XBUTTON1            = 0x05
 | 
			
		||||
	VK_XBUTTON2            = 0x06
 | 
			
		||||
	VK_BACK                = 0x08
 | 
			
		||||
	VK_TAB                 = 0x09
 | 
			
		||||
	VK_CLEAR               = 0x0C
 | 
			
		||||
	VK_ENTER               = 0x0D
 | 
			
		||||
	VK_PAUSE               = 0x13
 | 
			
		||||
	VK_CAPITAL             = 0x14
 | 
			
		||||
	VK_KANA                = 0x15
 | 
			
		||||
	VK_HANGUEL             = 0x15
 | 
			
		||||
	VK_HANGUL              = 0x15
 | 
			
		||||
	VK_JUNJA               = 0x17
 | 
			
		||||
	VK_FINAL               = 0x18
 | 
			
		||||
	VK_HANJA               = 0x19
 | 
			
		||||
	VK_KANJI               = 0x19
 | 
			
		||||
	VK_ESC                 = 0x1B
 | 
			
		||||
	VK_CONVERT             = 0x1C
 | 
			
		||||
	VK_NONCONVERT          = 0x1D
 | 
			
		||||
	VK_ACCEPT              = 0x1E
 | 
			
		||||
	VK_MODECHANGE          = 0x1F
 | 
			
		||||
	VK_SPACE               = 0x20
 | 
			
		||||
	VK_PRIOR               = 0x21
 | 
			
		||||
	VK_NEXT                = 0x22
 | 
			
		||||
	VK_END                 = 0x23
 | 
			
		||||
	VK_HOME                = 0x24
 | 
			
		||||
	VK_LEFT                = 0x25
 | 
			
		||||
	VK_UP                  = 0x26
 | 
			
		||||
	VK_RIGHT               = 0x27
 | 
			
		||||
	VK_DOWN                = 0x28
 | 
			
		||||
	VK_SELECT              = 0x29
 | 
			
		||||
	VK_PRINT               = 0x2A
 | 
			
		||||
	VK_EXECUTE             = 0x2B
 | 
			
		||||
	VK_SNAPSHOT            = 0x2C
 | 
			
		||||
	VK_INSERT              = 0x2D
 | 
			
		||||
	VK_DELETE              = 0x2E
 | 
			
		||||
	VK_HELP                = 0x2F
 | 
			
		||||
	VK_0                   = 0x30
 | 
			
		||||
	VK_1                   = 0x31
 | 
			
		||||
	VK_2                   = 0x32
 | 
			
		||||
	VK_3                   = 0x33
 | 
			
		||||
	VK_4                   = 0x34
 | 
			
		||||
	VK_5                   = 0x35
 | 
			
		||||
	VK_6                   = 0x36
 | 
			
		||||
	VK_7                   = 0x37
 | 
			
		||||
	VK_8                   = 0x38
 | 
			
		||||
	VK_9                   = 0x39
 | 
			
		||||
	VK_A                   = 0x41
 | 
			
		||||
	VK_B                   = 0x42
 | 
			
		||||
	VK_C                   = 0x43
 | 
			
		||||
	VK_D                   = 0x44
 | 
			
		||||
	VK_E                   = 0x45
 | 
			
		||||
	VK_F                   = 0x46
 | 
			
		||||
	VK_G                   = 0x47
 | 
			
		||||
	VK_H                   = 0x48
 | 
			
		||||
	VK_I                   = 0x49
 | 
			
		||||
	VK_J                   = 0x4A
 | 
			
		||||
	VK_K                   = 0x4B
 | 
			
		||||
	VK_L                   = 0x4C
 | 
			
		||||
	VK_M                   = 0x4D
 | 
			
		||||
	VK_N                   = 0x4E
 | 
			
		||||
	VK_O                   = 0x4F
 | 
			
		||||
	VK_P                   = 0x50
 | 
			
		||||
	VK_Q                   = 0x51
 | 
			
		||||
	VK_R                   = 0x52
 | 
			
		||||
	VK_S                   = 0x53
 | 
			
		||||
	VK_T                   = 0x54
 | 
			
		||||
	VK_U                   = 0x55
 | 
			
		||||
	VK_V                   = 0x56
 | 
			
		||||
	VK_W                   = 0x57
 | 
			
		||||
	VK_X                   = 0x58
 | 
			
		||||
	VK_Y                   = 0x59
 | 
			
		||||
	VK_Z                   = 0x5A
 | 
			
		||||
	VK_LWIN                = 0x5B
 | 
			
		||||
	VK_RWIN                = 0x5C
 | 
			
		||||
	VK_APPS                = 0x5D
 | 
			
		||||
	VK_SLEEP               = 0x5F
 | 
			
		||||
	VK_NUMPAD0             = 0x60
 | 
			
		||||
	VK_NUMPAD1             = 0x61
 | 
			
		||||
	VK_NUMPAD2             = 0x62
 | 
			
		||||
	VK_NUMPAD3             = 0x63
 | 
			
		||||
	VK_NUMPAD4             = 0x64
 | 
			
		||||
	VK_NUMPAD5             = 0x65
 | 
			
		||||
	VK_NUMPAD6             = 0x66
 | 
			
		||||
	VK_NUMPAD7             = 0x67
 | 
			
		||||
	VK_NUMPAD8             = 0x68
 | 
			
		||||
	VK_NUMPAD9             = 0x69
 | 
			
		||||
	VK_MULTIPLY            = 0x6A
 | 
			
		||||
	VK_ADD                 = 0x6B
 | 
			
		||||
	VK_SEPARATOR           = 0x6C
 | 
			
		||||
	VK_SUBTRACT            = 0x6D
 | 
			
		||||
	VK_DECIMAL             = 0x6E
 | 
			
		||||
	VK_DIVIDE              = 0x6F
 | 
			
		||||
	VK_F1                  = 0x70
 | 
			
		||||
	VK_F2                  = 0x71
 | 
			
		||||
	VK_F3                  = 0x72
 | 
			
		||||
	VK_F4                  = 0x73
 | 
			
		||||
	VK_F5                  = 0x74
 | 
			
		||||
	VK_F6                  = 0x75
 | 
			
		||||
	VK_F7                  = 0x76
 | 
			
		||||
	VK_F8                  = 0x77
 | 
			
		||||
	VK_F9                  = 0x78
 | 
			
		||||
	VK_F10                 = 0x79
 | 
			
		||||
	VK_F11                 = 0x7A
 | 
			
		||||
	VK_F12                 = 0x7B
 | 
			
		||||
	VK_F13                 = 0x7C
 | 
			
		||||
	VK_F14                 = 0x7D
 | 
			
		||||
	VK_F15                 = 0x7E
 | 
			
		||||
	VK_F16                 = 0x7F
 | 
			
		||||
	VK_F17                 = 0x80
 | 
			
		||||
	VK_F18                 = 0x81
 | 
			
		||||
	VK_F19                 = 0x82
 | 
			
		||||
	VK_F20                 = 0x83
 | 
			
		||||
	VK_F21                 = 0x84
 | 
			
		||||
	VK_F22                 = 0x85
 | 
			
		||||
	VK_F23                 = 0x86
 | 
			
		||||
	VK_F24                 = 0x87
 | 
			
		||||
	VK_NUMLOCK             = 0x90
 | 
			
		||||
	VK_SCROLL              = 0x91
 | 
			
		||||
	VK_LMENU               = 0xA4
 | 
			
		||||
	VK_RMENU               = 0xA5
 | 
			
		||||
	VK_BROWSER_BACK        = 0xA6
 | 
			
		||||
	VK_BROWSER_FORWARD     = 0xA7
 | 
			
		||||
	VK_BROWSER_REFRESH     = 0xA8
 | 
			
		||||
	VK_BROWSER_STOP        = 0xA9
 | 
			
		||||
	VK_BROWSER_SEARCH      = 0xAA
 | 
			
		||||
	VK_BROWSER_FAVORITES   = 0xAB
 | 
			
		||||
	VK_BROWSER_HOME        = 0xAC
 | 
			
		||||
	VK_VOLUME_MUTE         = 0xAD
 | 
			
		||||
	VK_VOLUME_DOWN         = 0xAE
 | 
			
		||||
	VK_VOLUME_UP           = 0xAF
 | 
			
		||||
	VK_MEDIA_NEXT_TRACK    = 0xB0
 | 
			
		||||
	VK_MEDIA_PREV_TRACK    = 0xB1
 | 
			
		||||
	VK_MEDIA_STOP          = 0xB2
 | 
			
		||||
	VK_MEDIA_PLAY_PAUSE    = 0xB3
 | 
			
		||||
	VK_LAUNCH_MAIL         = 0xB4
 | 
			
		||||
	VK_LAUNCH_MEDIA_SELECT = 0xB5
 | 
			
		||||
	VK_LAUNCH_APP1         = 0xB6
 | 
			
		||||
	VK_LAUNCH_APP2         = 0xB7
 | 
			
		||||
	VK_OEM_1               = 0xBA
 | 
			
		||||
	VK_OEM_PLUS            = 0xBB
 | 
			
		||||
	VK_OEM_COMMA           = 0xBC
 | 
			
		||||
	VK_OEM_MINUS           = 0xBD
 | 
			
		||||
	VK_OEM_PERIOD          = 0xBE
 | 
			
		||||
	VK_OEM_2               = 0xBF
 | 
			
		||||
	VK_OEM_3               = 0xC0
 | 
			
		||||
	VK_OEM_4               = 0xDB
 | 
			
		||||
	VK_OEM_5               = 0xDC
 | 
			
		||||
	VK_OEM_6               = 0xDD
 | 
			
		||||
	VK_OEM_7               = 0xDE
 | 
			
		||||
	VK_OEM_8               = 0xDF
 | 
			
		||||
	VK_OEM_102             = 0xE2
 | 
			
		||||
	VK_PROCESSKEY          = 0xE5
 | 
			
		||||
	VK_PACKET              = 0xE7
 | 
			
		||||
	VK_ATTN                = 0xF6
 | 
			
		||||
	VK_CRSEL               = 0xF7
 | 
			
		||||
	VK_EXSEL               = 0xF8
 | 
			
		||||
	VK_EREOF               = 0xF9
 | 
			
		||||
	VK_PLAY                = 0xFA
 | 
			
		||||
	VK_ZOOM                = 0xFB
 | 
			
		||||
	VK_NONAME              = 0xFC
 | 
			
		||||
	VK_PA1                 = 0xFD
 | 
			
		||||
	VK_OEM_CLEAR           = 0xFE
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										32
									
								
								vendor/b612.me/win32api/userenv.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								vendor/b612.me/win32api/userenv.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
BOOL CreateEnvironmentBlock(
 | 
			
		||||
  LPVOID *lpEnvironment,
 | 
			
		||||
  HANDLE hToken,
 | 
			
		||||
  BOOL   bInherit
 | 
			
		||||
);
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
func CreateEnvironmentBlock(lpEnvironment *HANDLE, hToken TOKEN, bInherit uintptr) error {
 | 
			
		||||
	userenv, err := syscall.LoadLibrary("userenv.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Userenv API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(userenv)
 | 
			
		||||
	Dup, err := syscall.GetProcAddress(syscall.Handle(userenv), "CreateEnvironmentBlock")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load WTSQueryUserToken API")
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall6(uintptr(Dup), 3, uintptr(unsafe.Pointer(lpEnvironment)), uintptr(hToken), bInherit, 0, 0, 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										146
									
								
								vendor/b612.me/win32api/win32api.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								vendor/b612.me/win32api/win32api.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,146 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type (
 | 
			
		||||
	ATOM                         uint16
 | 
			
		||||
	BOOL                         int32
 | 
			
		||||
	COLORREF                     uint32
 | 
			
		||||
	DWM_FRAME_COUNT              uint64
 | 
			
		||||
	DWORD                        uint32
 | 
			
		||||
	LPDWORD                      *uint32
 | 
			
		||||
	DWORDLONG                    uint64
 | 
			
		||||
	HACCEL                       HANDLE
 | 
			
		||||
	HANDLE                       uintptr
 | 
			
		||||
	HBITMAP                      HANDLE
 | 
			
		||||
	HBRUSH                       HANDLE
 | 
			
		||||
	HCURSOR                      HANDLE
 | 
			
		||||
	HDC                          HANDLE
 | 
			
		||||
	HDROP                        HANDLE
 | 
			
		||||
	HDWP                         HANDLE
 | 
			
		||||
	HENHMETAFILE                 HANDLE
 | 
			
		||||
	HFONT                        HANDLE
 | 
			
		||||
	HGDIOBJ                      HANDLE
 | 
			
		||||
	HGLOBAL                      HANDLE
 | 
			
		||||
	HGLRC                        HANDLE
 | 
			
		||||
	HHOOK                        HANDLE
 | 
			
		||||
	HICON                        HANDLE
 | 
			
		||||
	HIMAGELIST                   HANDLE
 | 
			
		||||
	HINSTANCE                    HANDLE
 | 
			
		||||
	HKEY                         HANDLE
 | 
			
		||||
	HKL                          HANDLE
 | 
			
		||||
	HMENU                        HANDLE
 | 
			
		||||
	HMODULE                      HANDLE
 | 
			
		||||
	HMONITOR                     HANDLE
 | 
			
		||||
	HPEN                         HANDLE
 | 
			
		||||
	HRESULT                      int32
 | 
			
		||||
	HRGN                         HANDLE
 | 
			
		||||
	HRSRC                        HANDLE
 | 
			
		||||
	HTHUMBNAIL                   HANDLE
 | 
			
		||||
	HWND                         HANDLE
 | 
			
		||||
	LPARAM                       uintptr
 | 
			
		||||
	LPCVOID                      unsafe.Pointer
 | 
			
		||||
	LPVOID                       unsafe.Pointer
 | 
			
		||||
	LRESULT                      uintptr
 | 
			
		||||
	LPCWSTR                      *uint16
 | 
			
		||||
	PVOID                        unsafe.Pointer
 | 
			
		||||
	QPC_TIME                     uint64
 | 
			
		||||
	ULONG                        uint32
 | 
			
		||||
	ULONG_PTR                    uintptr
 | 
			
		||||
	WPARAM                       uintptr
 | 
			
		||||
	WTS_CONNECTSTATE_CLASS       int
 | 
			
		||||
	TRACEHANDLE                  uintptr
 | 
			
		||||
	TOKEN                        HANDLE
 | 
			
		||||
	LPWSTR                       *uint16
 | 
			
		||||
	TOKEN_TYPE                   int
 | 
			
		||||
	SW                           int
 | 
			
		||||
	SECURITY_IMPERSONATION_LEVEL int
 | 
			
		||||
	WCHAR                        uint16
 | 
			
		||||
	WORD                         uint16
 | 
			
		||||
	USN                          int64
 | 
			
		||||
	LARGE_INTEGER                LONGLONG
 | 
			
		||||
	LONGLONG                     int64
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type WTS_SESSION_INFO struct {
 | 
			
		||||
	SessionID      HANDLE
 | 
			
		||||
	WinStationName *uint16
 | 
			
		||||
	State          WTS_CONNECTSTATE_CLASS
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	WTS_CURRENT_SERVER_HANDLE uintptr = 0
 | 
			
		||||
)
 | 
			
		||||
const (
 | 
			
		||||
	WTSActive WTS_CONNECTSTATE_CLASS = iota
 | 
			
		||||
	WTSConnected
 | 
			
		||||
	WTSConnectQuery
 | 
			
		||||
	WTSShadow
 | 
			
		||||
	WTSDisconnected
 | 
			
		||||
	WTSIdle
 | 
			
		||||
	WTSListen
 | 
			
		||||
	WTSReset
 | 
			
		||||
	WTSDown
 | 
			
		||||
	WTSInit
 | 
			
		||||
)
 | 
			
		||||
const (
 | 
			
		||||
	SecurityAnonymous SECURITY_IMPERSONATION_LEVEL = iota
 | 
			
		||||
	SecurityIdentification
 | 
			
		||||
	SecurityImpersonation
 | 
			
		||||
	SecurityDelegation
 | 
			
		||||
)
 | 
			
		||||
const (
 | 
			
		||||
	TokenPrimary TOKEN_TYPE = iota + 1
 | 
			
		||||
	TokenImpersonazion
 | 
			
		||||
)
 | 
			
		||||
const (
 | 
			
		||||
	SW_HIDE            SW = 0
 | 
			
		||||
	SW_SHOWNORMAL         = 1
 | 
			
		||||
	SW_NORMAL             = 1
 | 
			
		||||
	SW_SHOWMINIMIZED      = 2
 | 
			
		||||
	SW_SHOWMAXIMIZED      = 3
 | 
			
		||||
	SW_MAXIMIZE           = 3
 | 
			
		||||
	SW_SHOWNOACTIVATE     = 4
 | 
			
		||||
	SW_SHOW               = 5
 | 
			
		||||
	SW_MINIMIZE           = 6
 | 
			
		||||
	SW_SHOWMINNOACTIVE    = 7
 | 
			
		||||
	SW_SHOWNA             = 8
 | 
			
		||||
	SW_RESTORE            = 9
 | 
			
		||||
	SW_SHOWDEFAULT        = 10
 | 
			
		||||
	SW_MAX                = 1
 | 
			
		||||
)
 | 
			
		||||
const (
 | 
			
		||||
	CREATE_UNICODE_ENVIRONMENT uint16 = 0x00000400
 | 
			
		||||
	CREATE_NO_WINDOW                  = 0x08000000
 | 
			
		||||
	CREATE_NEW_CONSOLE                = 0x00000010
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type StartupInfo struct {
 | 
			
		||||
	Cb            uint32
 | 
			
		||||
	_             *uint16
 | 
			
		||||
	Desktop       *uint16
 | 
			
		||||
	Title         *uint16
 | 
			
		||||
	X             uint32
 | 
			
		||||
	Y             uint32
 | 
			
		||||
	XSize         uint32
 | 
			
		||||
	YSize         uint32
 | 
			
		||||
	XCountChars   uint32
 | 
			
		||||
	YCountChars   uint32
 | 
			
		||||
	FillAttribute uint32
 | 
			
		||||
	Flags         uint32
 | 
			
		||||
	ShowWindow    uint16
 | 
			
		||||
	_             uint16
 | 
			
		||||
	_             *byte
 | 
			
		||||
	StdInput      HANDLE
 | 
			
		||||
	StdOutput     HANDLE
 | 
			
		||||
	StdErr        HANDLE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ProcessInformation struct {
 | 
			
		||||
	Process   HANDLE
 | 
			
		||||
	Thread    HANDLE
 | 
			
		||||
	ProcessId uint32
 | 
			
		||||
	ThreadId  uint32
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/b612.me/win32api/wtsapi32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/b612.me/win32api/wtsapi32.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
package win32api
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func WTSQueryUserToken(SessionId HANDLE, phToken *HANDLE) error {
 | 
			
		||||
	wtsapi32, err := syscall.LoadLibrary("wtsapi32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Wtsapi32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(wtsapi32)
 | 
			
		||||
	WTGet, err := syscall.GetProcAddress(syscall.Handle(wtsapi32), "WTSQueryUserToken")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load WTSQueryUserToken API")
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall(uintptr(WTGet), 2, uintptr(SessionId), uintptr(unsafe.Pointer(phToken)), 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	} else {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func WTSEnumerateSessions(hServer HANDLE, Reserved, Version DWORD, ppSessionInfo *HANDLE, pCount *int) error {
 | 
			
		||||
	wtsapi32, err := syscall.LoadLibrary("wtsapi32.dll")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load Wtsapi32 API")
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.FreeLibrary(wtsapi32)
 | 
			
		||||
	WT, err := syscall.GetProcAddress(syscall.Handle(wtsapi32), "WTSEnumerateSessionsW")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return errors.New("Can't Load WTSQueryUserToken API")
 | 
			
		||||
	}
 | 
			
		||||
	r, _, errno := syscall.Syscall6(uintptr(WT), 5, uintptr(hServer), uintptr(Reserved), uintptr(Version), uintptr(unsafe.Pointer(ppSessionInfo)), uintptr(unsafe.Pointer(pCount)), 0)
 | 
			
		||||
	if r == 0 {
 | 
			
		||||
		return error(errno)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/b612.me/wincmd/disk.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vendor/b612.me/wincmd/disk.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
package wincmd
 | 
			
		||||
 | 
			
		||||
import "b612.me/wincmd/ntfs/usn"
 | 
			
		||||
 | 
			
		||||
func ListDrivers() ([]string, error) {
 | 
			
		||||
	return usn.ListDrivers()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetDiskInfo(disk string) (usn.DiskInfo, error) {
 | 
			
		||||
	return usn.GetDiskInfo(disk)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										256
									
								
								vendor/b612.me/wincmd/ntfs/usn/filestats_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								vendor/b612.me/wincmd/ntfs/usn/filestats_windows.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,256 @@
 | 
			
		||||
package usn
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/win32api"
 | 
			
		||||
	"golang.org/x/sys/windows"
 | 
			
		||||
	"os"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const DevNull = "NUL"
 | 
			
		||||
 | 
			
		||||
// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
 | 
			
		||||
type FileStat struct {
 | 
			
		||||
	name string
 | 
			
		||||
 | 
			
		||||
	// from ByHandleFileInformation, Win32FileAttributeData and Win32finddata
 | 
			
		||||
	FileAttributes uint32
 | 
			
		||||
	CreationTime   syscall.Filetime
 | 
			
		||||
	LastAccessTime syscall.Filetime
 | 
			
		||||
	LastWriteTime  syscall.Filetime
 | 
			
		||||
	FileSizeHigh   uint32
 | 
			
		||||
	FileSizeLow    uint32
 | 
			
		||||
 | 
			
		||||
	// from Win32finddata
 | 
			
		||||
	Reserved0 uint32
 | 
			
		||||
 | 
			
		||||
	// what syscall.GetFileType returns
 | 
			
		||||
	filetype uint32
 | 
			
		||||
 | 
			
		||||
	// used to implement SameFile
 | 
			
		||||
	sync.Mutex
 | 
			
		||||
	path             string
 | 
			
		||||
	vol              uint32
 | 
			
		||||
	idxhi            uint32
 | 
			
		||||
	idxlo            uint32
 | 
			
		||||
	appendNameToPath bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// newFileStatFromWin32finddata copies all required information
 | 
			
		||||
// from syscall.Win32finddata d into the newly created fileStat.
 | 
			
		||||
func newFileStatFromInformation(d *syscall.ByHandleFileInformation, name string, path string) FileStat {
 | 
			
		||||
	return FileStat{
 | 
			
		||||
		name:           name,
 | 
			
		||||
		path:           path,
 | 
			
		||||
		FileAttributes: d.FileAttributes,
 | 
			
		||||
		CreationTime:   d.CreationTime,
 | 
			
		||||
		LastAccessTime: d.LastAccessTime,
 | 
			
		||||
		LastWriteTime:  d.LastWriteTime,
 | 
			
		||||
		FileSizeHigh:   d.FileSizeHigh,
 | 
			
		||||
		FileSizeLow:    d.FileSizeLow,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fs *FileStat) Name() string {
 | 
			
		||||
	return fs.name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fs *FileStat) IsDir() bool {
 | 
			
		||||
	return fs.FileAttributes&win32api.FILE_ATTRIBUTE_DIRECTORY != 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fs *FileStat) isSymlink() bool {
 | 
			
		||||
	// Use instructions described at
 | 
			
		||||
	// https://blogs.msdn.microsoft.com/oldnewthing/20100212-00/?p=14963/
 | 
			
		||||
	// to recognize whether it's a symlink.
 | 
			
		||||
	if fs.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return fs.Reserved0 == syscall.IO_REPARSE_TAG_SYMLINK ||
 | 
			
		||||
		fs.Reserved0 == windows.IO_REPARSE_TAG_MOUNT_POINT
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fs *FileStat) Size() int64 {
 | 
			
		||||
	return int64(fs.FileSizeHigh)<<32 + int64(fs.FileSizeLow)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fs *FileStat) Mode() (m os.FileMode) {
 | 
			
		||||
	if fs == &devNullStat {
 | 
			
		||||
		return os.ModeDevice | os.ModeCharDevice | 0666
 | 
			
		||||
	}
 | 
			
		||||
	if fs.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 {
 | 
			
		||||
		m |= 0444
 | 
			
		||||
	} else {
 | 
			
		||||
		m |= 0666
 | 
			
		||||
	}
 | 
			
		||||
	if fs.isSymlink() {
 | 
			
		||||
		return m | os.ModeSymlink
 | 
			
		||||
	}
 | 
			
		||||
	if fs.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 {
 | 
			
		||||
		m |= os.ModeDir | 0111
 | 
			
		||||
	}
 | 
			
		||||
	switch fs.filetype {
 | 
			
		||||
	case syscall.FILE_TYPE_PIPE:
 | 
			
		||||
		m |= os.ModeNamedPipe
 | 
			
		||||
	case syscall.FILE_TYPE_CHAR:
 | 
			
		||||
		m |= os.ModeDevice | os.ModeCharDevice
 | 
			
		||||
	}
 | 
			
		||||
	return m
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fs *FileStat) ModTime() time.Time {
 | 
			
		||||
	return time.Unix(0, fs.LastWriteTime.Nanoseconds())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sys returns syscall.Win32FileAttributeData for file fs.
 | 
			
		||||
func (fs *FileStat) Sys() interface{} {
 | 
			
		||||
	return &syscall.Win32FileAttributeData{
 | 
			
		||||
		FileAttributes: fs.FileAttributes,
 | 
			
		||||
		CreationTime:   fs.CreationTime,
 | 
			
		||||
		LastAccessTime: fs.LastAccessTime,
 | 
			
		||||
		LastWriteTime:  fs.LastWriteTime,
 | 
			
		||||
		FileSizeHigh:   fs.FileSizeHigh,
 | 
			
		||||
		FileSizeLow:    fs.FileSizeLow,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// saveInfoFromPath saves full path of the file to be used by os.SameFile later,
 | 
			
		||||
// and set name from path.
 | 
			
		||||
 | 
			
		||||
// devNullStat is fileStat structure describing DevNull file ("NUL").
 | 
			
		||||
var devNullStat = FileStat{
 | 
			
		||||
	name: DevNull,
 | 
			
		||||
	// hopefully this will work for SameFile
 | 
			
		||||
	vol:   0,
 | 
			
		||||
	idxhi: 0,
 | 
			
		||||
	idxlo: 0,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fixLongPath(path string) string {
 | 
			
		||||
	// Do nothing (and don't allocate) if the path is "short".
 | 
			
		||||
	// Empirically (at least on the Windows Server 2013 builder),
 | 
			
		||||
	// the kernel is arbitrarily okay with < 248 bytes. That
 | 
			
		||||
	// matches what the docs above say:
 | 
			
		||||
	// "When using an API to create a directory, the specified
 | 
			
		||||
	// path cannot be so long that you cannot append an 8.3 file
 | 
			
		||||
	// name (that is, the directory name cannot exceed MAX_PATH
 | 
			
		||||
	// minus 12)." Since MAX_PATH is 260, 260 - 12 = 248.
 | 
			
		||||
	//
 | 
			
		||||
	// The MSDN docs appear to say that a normal path that is 248 bytes long
 | 
			
		||||
	// will work; empirically the path must be less then 248 bytes long.
 | 
			
		||||
	if len(path) < 248 {
 | 
			
		||||
		// Don't fix. (This is how Go 1.7 and earlier worked,
 | 
			
		||||
		// not automatically generating the \\?\ form)
 | 
			
		||||
		return path
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The extended form begins with \\?\, as in
 | 
			
		||||
	// \\?\c:\windows\foo.txt or \\?\UNC\server\share\foo.txt.
 | 
			
		||||
	// The extended form disables evaluation of . and .. path
 | 
			
		||||
	// elements and disables the interpretation of / as equivalent
 | 
			
		||||
	// to \. The conversion here rewrites / to \ and elides
 | 
			
		||||
	// . elements as well as trailing or duplicate separators. For
 | 
			
		||||
	// simplicity it avoids the conversion entirely for relative
 | 
			
		||||
	// paths or paths containing .. elements. For now,
 | 
			
		||||
	// \\server\share paths are not converted to
 | 
			
		||||
	// \\?\UNC\server\share paths because the rules for doing so
 | 
			
		||||
	// are less well-specified.
 | 
			
		||||
	if len(path) >= 2 && path[:2] == `\\` {
 | 
			
		||||
		// Don't canonicalize UNC paths.
 | 
			
		||||
		return path
 | 
			
		||||
	}
 | 
			
		||||
	if !isAbs(path) {
 | 
			
		||||
		// Relative path
 | 
			
		||||
		return path
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const prefix = `\\?`
 | 
			
		||||
 | 
			
		||||
	pathbuf := make([]byte, len(prefix)+len(path)+len(`\`))
 | 
			
		||||
	copy(pathbuf, prefix)
 | 
			
		||||
	n := len(path)
 | 
			
		||||
	r, w := 0, len(prefix)
 | 
			
		||||
	for r < n {
 | 
			
		||||
		switch {
 | 
			
		||||
		case IsPathSeparator(path[r]):
 | 
			
		||||
			// empty block
 | 
			
		||||
			r++
 | 
			
		||||
		case path[r] == '.' && (r+1 == n || IsPathSeparator(path[r+1])):
 | 
			
		||||
			// /./
 | 
			
		||||
			r++
 | 
			
		||||
		case r+1 < n && path[r] == '.' && path[r+1] == '.' && (r+2 == n || IsPathSeparator(path[r+2])):
 | 
			
		||||
			// /../ is currently unhandled
 | 
			
		||||
			return path
 | 
			
		||||
		default:
 | 
			
		||||
			pathbuf[w] = '\\'
 | 
			
		||||
			w++
 | 
			
		||||
			for ; r < n && !IsPathSeparator(path[r]); r++ {
 | 
			
		||||
				pathbuf[w] = path[r]
 | 
			
		||||
				w++
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// A drive's root directory needs a trailing \
 | 
			
		||||
	if w == len(`\\?\c:`) {
 | 
			
		||||
		pathbuf[w] = '\\'
 | 
			
		||||
		w++
 | 
			
		||||
	}
 | 
			
		||||
	return string(pathbuf[:w])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsPathSeparator(c uint8) bool {
 | 
			
		||||
	// NOTE: Windows accept / as path separator.
 | 
			
		||||
	return c == '\\' || c == '/'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isAbs(path string) (b bool) {
 | 
			
		||||
	v := volumeName(path)
 | 
			
		||||
	if v == "" {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	path = path[len(v):]
 | 
			
		||||
	if path == "" {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return IsPathSeparator(path[0])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func volumeName(path string) (v string) {
 | 
			
		||||
	if len(path) < 2 {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	// with drive letter
 | 
			
		||||
	c := path[0]
 | 
			
		||||
	if path[1] == ':' &&
 | 
			
		||||
		('0' <= c && c <= '9' || 'a' <= c && c <= 'z' ||
 | 
			
		||||
			'A' <= c && c <= 'Z') {
 | 
			
		||||
		return path[:2]
 | 
			
		||||
	}
 | 
			
		||||
	// is it UNC
 | 
			
		||||
	if l := len(path); l >= 5 && IsPathSeparator(path[0]) && IsPathSeparator(path[1]) &&
 | 
			
		||||
		!IsPathSeparator(path[2]) && path[2] != '.' {
 | 
			
		||||
		// first, leading `\\` and next shouldn't be `\`. its server name.
 | 
			
		||||
		for n := 3; n < l-1; n++ {
 | 
			
		||||
			// second, next '\' shouldn't be repeated.
 | 
			
		||||
			if IsPathSeparator(path[n]) {
 | 
			
		||||
				n++
 | 
			
		||||
				// third, following something characters. its share name.
 | 
			
		||||
				if !IsPathSeparator(path[n]) {
 | 
			
		||||
					if path[n] == '.' {
 | 
			
		||||
						break
 | 
			
		||||
					}
 | 
			
		||||
					for ; n < l; n++ {
 | 
			
		||||
						if IsPathSeparator(path[n]) {
 | 
			
		||||
							break
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					return path[:n]
 | 
			
		||||
				}
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return ""
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										596
									
								
								vendor/b612.me/wincmd/ntfs/usn/usn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										596
									
								
								vendor/b612.me/wincmd/ntfs/usn/usn.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,596 @@
 | 
			
		||||
package usn
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"b612.me/stario"
 | 
			
		||||
	"b612.me/win32api"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"syscall"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type DiskInfo struct {
 | 
			
		||||
	Driver       string
 | 
			
		||||
	Name         string
 | 
			
		||||
	Format       string
 | 
			
		||||
	SerialNumber uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ListDrivers() ([]string, error) {
 | 
			
		||||
	drivers := make([]string, 0, 26)
 | 
			
		||||
	buf := make([]uint16, 255)
 | 
			
		||||
	err := win32api.GetLogicalDriveStringsW(win32api.DWORD(len(buf)), &buf[0])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return drivers, err
 | 
			
		||||
	}
 | 
			
		||||
	var driver []rune
 | 
			
		||||
	for _, v := range buf {
 | 
			
		||||
		if v != 0 {
 | 
			
		||||
			driver = append(driver, rune(uint8(v)))
 | 
			
		||||
			if v == 92 {
 | 
			
		||||
				drivers = append(drivers, string(driver))
 | 
			
		||||
				driver = []rune{}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return drivers, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetDiskInfo(disk string) (DiskInfo, error) {
 | 
			
		||||
	format := make([]rune, 0, 12)
 | 
			
		||||
	name := make([]rune, 0, 128)
 | 
			
		||||
	ptr, _ := syscall.UTF16PtrFromString(disk)
 | 
			
		||||
	var lpVolumeNameBuffer = make([]uint16, syscall.MAX_PATH+1)
 | 
			
		||||
	var nVolumeNameSize = win32api.DWORD(len(lpVolumeNameBuffer))
 | 
			
		||||
	var lpVolumeSerialNumber uint32
 | 
			
		||||
	var lpMaximumComponentLength uint32
 | 
			
		||||
	var lpFileSystemFlags uint32
 | 
			
		||||
	var lpFileSystemNameBuffer = make([]uint16, 255)
 | 
			
		||||
	var nFileSystemNameSize uint32 = syscall.MAX_PATH + 1
 | 
			
		||||
	err := win32api.GetVolumeInformationW(ptr, &lpVolumeNameBuffer[0], nVolumeNameSize, &lpVolumeSerialNumber, &lpMaximumComponentLength,
 | 
			
		||||
		&lpFileSystemFlags, &lpFileSystemNameBuffer[0], win32api.DWORD(nFileSystemNameSize))
 | 
			
		||||
	for _, v := range lpFileSystemNameBuffer {
 | 
			
		||||
		if v != 0 {
 | 
			
		||||
			format = append(format, rune(v))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range lpVolumeNameBuffer {
 | 
			
		||||
		if v != 0 {
 | 
			
		||||
			name = append(name, rune(v))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return DiskInfo{
 | 
			
		||||
		SerialNumber: lpVolumeSerialNumber,
 | 
			
		||||
		Driver:       disk,
 | 
			
		||||
		Name:         string(name),
 | 
			
		||||
		Format:       string(format),
 | 
			
		||||
	}, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DeviceIoControl(handle syscall.Handle, controlCode uint32, in interface{}, out interface{}, done *uint32) (err error) {
 | 
			
		||||
	inPtr, inSize := getPointer(in)
 | 
			
		||||
	outPtr, outSize := getPointer(out)
 | 
			
		||||
	//_,err = syscall.Syscall9(procDeviceIoControl.Addr(), 8, uintptr(handle), uintptr(controlCode), inPtr, uintptr(inSize), outPtr, uintptr(outSize), uintptr(unsafe.Pointer(done)), uintptr(0), 0)
 | 
			
		||||
	_, err = win32api.DeviceIoControlPtr(win32api.HANDLE(handle), win32api.DWORD(controlCode), inPtr, win32api.DWORD(inSize), outPtr, win32api.DWORD(outSize), done, nil)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getPointer(i interface{}) (pointer, size uintptr) {
 | 
			
		||||
	v := reflect.ValueOf(i)
 | 
			
		||||
	switch k := v.Kind(); k {
 | 
			
		||||
	case reflect.Ptr:
 | 
			
		||||
		t := v.Elem().Type()
 | 
			
		||||
		size = t.Size()
 | 
			
		||||
		pointer = v.Pointer()
 | 
			
		||||
	case reflect.Slice:
 | 
			
		||||
		size = uintptr(v.Cap())
 | 
			
		||||
		pointer = v.Pointer()
 | 
			
		||||
	default:
 | 
			
		||||
		fmt.Println("error")
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Need a custom Open to work with backup_semantics
 | 
			
		||||
func CreateFile(path string, mode int, attrs uint32) (fd syscall.Handle, err error) {
 | 
			
		||||
	if len(path) == 0 {
 | 
			
		||||
		return syscall.InvalidHandle, win32api.ERROR_FILE_NOT_FOUND
 | 
			
		||||
	}
 | 
			
		||||
	pathp, err := syscall.UTF16PtrFromString(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return syscall.InvalidHandle, err
 | 
			
		||||
	}
 | 
			
		||||
	var access uint32
 | 
			
		||||
	switch mode & (win32api.O_RDONLY | win32api.O_WRONLY | win32api.O_RDWR) {
 | 
			
		||||
	case win32api.O_RDONLY:
 | 
			
		||||
		access = win32api.GENERIC_READ
 | 
			
		||||
	case win32api.O_WRONLY:
 | 
			
		||||
		access = win32api.GENERIC_WRITE
 | 
			
		||||
	case win32api.O_RDWR:
 | 
			
		||||
		access = win32api.GENERIC_READ | win32api.GENERIC_WRITE
 | 
			
		||||
	}
 | 
			
		||||
	if mode&win32api.O_CREAT != 0 {
 | 
			
		||||
		access |= win32api.GENERIC_WRITE
 | 
			
		||||
	}
 | 
			
		||||
	if mode&win32api.O_APPEND != 0 {
 | 
			
		||||
		access &^= win32api.GENERIC_WRITE
 | 
			
		||||
		access |= win32api.FILE_APPEND_DATA
 | 
			
		||||
	}
 | 
			
		||||
	sharemode := uint32(win32api.FILE_SHARE_READ | win32api.FILE_SHARE_WRITE)
 | 
			
		||||
	var sa *syscall.SecurityAttributes
 | 
			
		||||
	if mode&win32api.O_CLOEXEC == 0 {
 | 
			
		||||
		sa = makeInheritSa()
 | 
			
		||||
	}
 | 
			
		||||
	var createmode uint32
 | 
			
		||||
	switch {
 | 
			
		||||
	case mode&(win32api.O_CREAT|win32api.O_EXCL) == (win32api.O_CREAT | win32api.O_EXCL):
 | 
			
		||||
		createmode = win32api.CREATE_NEW
 | 
			
		||||
	case mode&(win32api.O_CREAT|win32api.O_TRUNC) == (win32api.O_CREAT | win32api.O_TRUNC):
 | 
			
		||||
		createmode = win32api.CREATE_ALWAYS
 | 
			
		||||
	case mode&win32api.O_CREAT == win32api.O_CREAT:
 | 
			
		||||
		createmode = win32api.OPEN_ALWAYS
 | 
			
		||||
	case mode&win32api.O_TRUNC == win32api.O_TRUNC:
 | 
			
		||||
		createmode = win32api.TRUNCATE_EXISTING
 | 
			
		||||
	default:
 | 
			
		||||
		createmode = win32api.OPEN_EXISTING
 | 
			
		||||
	}
 | 
			
		||||
	h, e := syscall.CreateFile(pathp, access, sharemode, sa, createmode, attrs, 0)
 | 
			
		||||
	return h, e
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func makeInheritSa() *syscall.SecurityAttributes {
 | 
			
		||||
	var sa syscall.SecurityAttributes
 | 
			
		||||
	sa.Length = uint32(unsafe.Sizeof(sa))
 | 
			
		||||
	sa.InheritHandle = 1
 | 
			
		||||
	return &sa
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Query usn journal data
 | 
			
		||||
func queryUsnJournal(fd syscall.Handle) (ujd win32api.USN_JOURNAL_DATA, done uint32, err error) {
 | 
			
		||||
	err = DeviceIoControl(fd, win32api.FSCTL_QUERY_USN_JOURNAL, []byte{}, &ujd, &done)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func readUsnJournal(fd syscall.Handle, rujd *win32api.READ_USN_JOURNAL_DATA) (data []byte, done uint32, err error) {
 | 
			
		||||
	data = make([]byte, 0x1000)
 | 
			
		||||
	err = DeviceIoControl(fd, win32api.FSCTL_READ_USN_JOURNAL, rujd, data, &done)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func enumUsnData(fd syscall.Handle, med *win32api.MFT_ENUM_DATA) (data []byte, done uint32, err error) {
 | 
			
		||||
	data = make([]byte, 0x10000)
 | 
			
		||||
	err = DeviceIoControl(fd, win32api.FSCTL_ENUM_USN_DATA, med, data, &done)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FileEntry struct {
 | 
			
		||||
	Name   string
 | 
			
		||||
	Parent win32api.DWORDLONG
 | 
			
		||||
	Type   uint8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type FileMonitor struct {
 | 
			
		||||
	Name   string
 | 
			
		||||
	Self   win32api.DWORDLONG
 | 
			
		||||
	Parent win32api.DWORDLONG
 | 
			
		||||
	Type   uint8
 | 
			
		||||
	Reason string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ListUsnFile(driver string) (map[win32api.DWORDLONG]FileEntry, error) {
 | 
			
		||||
	fileMap := make(map[win32api.DWORDLONG]FileEntry)
 | 
			
		||||
	pDriver := "\\\\.\\" + driver[:len(driver)-1]
 | 
			
		||||
	fd, err := CreateFile(pDriver, syscall.O_RDONLY, win32api.FILE_ATTRIBUTE_NORMAL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fileMap, err
 | 
			
		||||
	}
 | 
			
		||||
	ujd, _, err := queryUsnJournal(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fileMap, err
 | 
			
		||||
	}
 | 
			
		||||
	med := win32api.MFT_ENUM_DATA{0, 0, ujd.NextUsn}
 | 
			
		||||
	for {
 | 
			
		||||
		data, done, err := enumUsnData(fd, &med)
 | 
			
		||||
		if err != nil && done != 0 {
 | 
			
		||||
			return fileMap, err
 | 
			
		||||
		}
 | 
			
		||||
		if done == 0 {
 | 
			
		||||
			return fileMap, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var usn win32api.USN = *(*win32api.USN)(unsafe.Pointer(&data[0]))
 | 
			
		||||
		// fmt.Println("usn", usn)
 | 
			
		||||
 | 
			
		||||
		var ur *win32api.USN_RECORD
 | 
			
		||||
		for i := unsafe.Sizeof(usn); i < uintptr(done); i += uintptr(ur.RecordLength) {
 | 
			
		||||
			ur = (*win32api.USN_RECORD)(unsafe.Pointer(&data[i]))
 | 
			
		||||
			nameLength := uintptr(ur.FileNameLength) / unsafe.Sizeof(ur.FileName[0])
 | 
			
		||||
			fnp := unsafe.Pointer(&data[i+uintptr(ur.FileNameOffset)])
 | 
			
		||||
			fnUtf := (*[10000]uint16)(fnp)[:nameLength]
 | 
			
		||||
			fn := syscall.UTF16ToString(fnUtf)
 | 
			
		||||
			(*reflect.SliceHeader)(unsafe.Pointer(&fn)).Cap = int(nameLength)
 | 
			
		||||
			typed := uint8(0)
 | 
			
		||||
			if ur.FileAttributes&win32api.FILE_ATTRIBUTE_DIRECTORY != 0 {
 | 
			
		||||
				typed = 1
 | 
			
		||||
			}
 | 
			
		||||
			// fmt.Println("len", ur.FileNameLength, ur.FileNameOffset, "fn", fn)
 | 
			
		||||
			fileMap[ur.FileReferenceNumber] = FileEntry{Name: fn, Parent: ur.ParentFileReferenceNumber, Type: typed}
 | 
			
		||||
		}
 | 
			
		||||
		med.StartFileReferenceNumber = win32api.DWORDLONG(usn)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ListUsnFileFn(driver string, searchFn func(string, bool) bool) (map[win32api.DWORDLONG]FileEntry, error) {
 | 
			
		||||
	fileMap := make(map[win32api.DWORDLONG]FileEntry)
 | 
			
		||||
	pDriver := "\\\\.\\" + driver[:len(driver)-1]
 | 
			
		||||
	fd, err := CreateFile(pDriver, syscall.O_RDONLY, win32api.FILE_ATTRIBUTE_NORMAL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fileMap, err
 | 
			
		||||
	}
 | 
			
		||||
	ujd, _, err := queryUsnJournal(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fileMap, err
 | 
			
		||||
	}
 | 
			
		||||
	med := win32api.MFT_ENUM_DATA{0, 0, ujd.NextUsn}
 | 
			
		||||
	for {
 | 
			
		||||
		data, done, err := enumUsnData(fd, &med)
 | 
			
		||||
		if err != nil && done != 0 {
 | 
			
		||||
			return fileMap, err
 | 
			
		||||
		}
 | 
			
		||||
		if done == 0 {
 | 
			
		||||
			return fileMap, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var usn win32api.USN = *(*win32api.USN)(unsafe.Pointer(&data[0]))
 | 
			
		||||
		// fmt.Println("usn", usn)
 | 
			
		||||
 | 
			
		||||
		var ur *win32api.USN_RECORD
 | 
			
		||||
		for i := unsafe.Sizeof(usn); i < uintptr(done); i += uintptr(ur.RecordLength) {
 | 
			
		||||
			ur = (*win32api.USN_RECORD)(unsafe.Pointer(&data[i]))
 | 
			
		||||
			nameLength := uintptr(ur.FileNameLength) / unsafe.Sizeof(ur.FileName[0])
 | 
			
		||||
			fnp := unsafe.Pointer(&data[i+uintptr(ur.FileNameOffset)])
 | 
			
		||||
			fnUtf := (*[10000]uint16)(fnp)[:nameLength]
 | 
			
		||||
			fn := syscall.UTF16ToString(fnUtf)
 | 
			
		||||
			(*reflect.SliceHeader)(unsafe.Pointer(&fn)).Cap = int(nameLength)
 | 
			
		||||
			typed := uint8(0)
 | 
			
		||||
			if ur.FileAttributes&win32api.FILE_ATTRIBUTE_DIRECTORY != 0 {
 | 
			
		||||
				typed = 1
 | 
			
		||||
			}
 | 
			
		||||
			if typed == 1 || searchFn(fn, typed == 1) {
 | 
			
		||||
				// fmt.Println("len", ur.FileNameLength, ur.FileNameOffset, "fn", fn)
 | 
			
		||||
				fileMap[ur.FileReferenceNumber] = FileEntry{Name: fn, Parent: ur.ParentFileReferenceNumber, Type: typed}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		med.StartFileReferenceNumber = win32api.DWORDLONG(usn)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFullUsnPath(diskName string, fileMap map[win32api.DWORDLONG]FileEntry, id win32api.DWORDLONG) (name string) {
 | 
			
		||||
	for id != 0 {
 | 
			
		||||
		fe := fileMap[id]
 | 
			
		||||
		if id == fe.Parent {
 | 
			
		||||
			name = "\\" + name
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if name == "" {
 | 
			
		||||
			name = fe.Name
 | 
			
		||||
		} else {
 | 
			
		||||
			name = fe.Name + "\\" + name
 | 
			
		||||
		}
 | 
			
		||||
		id = fe.Parent
 | 
			
		||||
	}
 | 
			
		||||
	name = diskName[:len(diskName)-1] + name
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetFullUsnPathEntry(diskName string, fileMap map[win32api.DWORDLONG]FileEntry, en FileMonitor) (name string) {
 | 
			
		||||
	fileMap[en.Self] = FileEntry{
 | 
			
		||||
		Name:   en.Name,
 | 
			
		||||
		Parent: en.Parent,
 | 
			
		||||
		Type:   en.Type,
 | 
			
		||||
	}
 | 
			
		||||
	id := en.Self
 | 
			
		||||
	for id != 0 {
 | 
			
		||||
		fe := fileMap[id]
 | 
			
		||||
		if id == fe.Parent {
 | 
			
		||||
			name = "\\" + name
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if name == "" {
 | 
			
		||||
			name = fe.Name
 | 
			
		||||
		} else {
 | 
			
		||||
			name = fe.Name + "\\" + name
 | 
			
		||||
		}
 | 
			
		||||
		id = fe.Parent
 | 
			
		||||
	}
 | 
			
		||||
	name = diskName[:len(diskName)-1] + name
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	ALL_FILES = iota
 | 
			
		||||
	ONLY_FOLDER
 | 
			
		||||
	NO_FOLDER
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func ListNTFSUsnDriverFilesFn(diskName string, searchFn func(string, bool) bool) ([]string, error) {
 | 
			
		||||
	var result []string
 | 
			
		||||
	data, err := ListUsnFileFn(diskName, searchFn)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return result, err
 | 
			
		||||
	}
 | 
			
		||||
	return listNTFSUsnDriverFiles(diskName, searchFn, data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ListNTFSUsnDriverFiles(diskName string, folder uint8) ([]string, error) {
 | 
			
		||||
	var result []string
 | 
			
		||||
	data, err := ListUsnFile(diskName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return result, err
 | 
			
		||||
	}
 | 
			
		||||
	return listNTFSUsnDriverFiles(diskName, func(name string, tp bool) bool {
 | 
			
		||||
		if !tp && folder == ONLY_FOLDER {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		if tp && folder == NO_FOLDER {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		return true
 | 
			
		||||
	}, data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listNTFSUsnDriverFiles(diskName string, fn func(string, bool) bool, data map[win32api.DWORDLONG]FileEntry) ([]string, error) {
 | 
			
		||||
	result := make([]string, len(data))
 | 
			
		||||
	i := 0
 | 
			
		||||
	for k, v := range data {
 | 
			
		||||
		if !fn(v.Name, v.Type == 1) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		name := GetFullUsnPath(diskName, data, k)
 | 
			
		||||
		result[i] = name
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
	(*reflect.SliceHeader)(unsafe.Pointer(&result)).Cap = i
 | 
			
		||||
	(*reflect.SliceHeader)(unsafe.Pointer(&result)).Len = i
 | 
			
		||||
	data = nil
 | 
			
		||||
	data = make(map[win32api.DWORDLONG]FileEntry, 0)
 | 
			
		||||
	runtime.GC()
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ListNTFSUsnDriverInfoFn(diskName string, searchFn func(string, bool) bool) ([]FileStat, error) {
 | 
			
		||||
	data, err := ListUsnFileFn(diskName, searchFn)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return listNTFSUsnDriverInfo(diskName, searchFn, data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ListNTFSUsnDriverInfo(diskName string, folder uint8) ([]FileStat, error) {
 | 
			
		||||
	data, err := ListUsnFile(diskName)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return listNTFSUsnDriverInfo(diskName, func(name string, tp bool) bool {
 | 
			
		||||
		if !tp && folder == ONLY_FOLDER {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		if tp && folder == NO_FOLDER {
 | 
			
		||||
			return false
 | 
			
		||||
		}
 | 
			
		||||
		return true
 | 
			
		||||
	}, data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listNTFSUsnDriverInfo(diskName string, fn func(string, bool) bool, data map[win32api.DWORDLONG]FileEntry) ([]FileStat, error) {
 | 
			
		||||
	//fmt.Println("finished 1")
 | 
			
		||||
	pDriver := "\\\\.\\" + diskName[:len(diskName)-1]
 | 
			
		||||
	fd, err := CreateFile(pDriver, syscall.O_RDONLY, win32api.FILE_ATTRIBUTE_NORMAL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.Close(fd)
 | 
			
		||||
	result := make([]FileStat, len(data))
 | 
			
		||||
	i := int(0)
 | 
			
		||||
	wg := stario.NewWaitGroup(100)
 | 
			
		||||
	for k, v := range data {
 | 
			
		||||
		if !fn(v.Name, v.Type == 1) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		wg.Add(1)
 | 
			
		||||
		go func(k win32api.DWORDLONG, v FileEntry, i int) {
 | 
			
		||||
			defer wg.Done()
 | 
			
		||||
			//now := time.Now().UnixNano()
 | 
			
		||||
			/*
 | 
			
		||||
				fd2, err := OpenFileByIdWithfd(fd, k, syscall.O_RDONLY, win32api.FILE_ATTRIBUTE_NORMAL)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
				//fmt.Println("cost", float64((time.Now().UnixNano()-now)/1000000))
 | 
			
		||||
				var info syscall.ByHandleFileInformation
 | 
			
		||||
				err = syscall.GetFileInformationByHandle(fd2, &info)
 | 
			
		||||
				syscall.Close(fd2)
 | 
			
		||||
				//fmt.Println("cost", float64((time.Now().UnixNano()-now)/1000000))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			*/
 | 
			
		||||
			path := GetFullUsnPath(diskName, data, k)
 | 
			
		||||
			fileInfo, err := os.Stat(path)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			fs := fileInfo.Sys().(*syscall.Win32FileAttributeData)
 | 
			
		||||
			stat := FileStat{
 | 
			
		||||
				FileAttributes: fs.FileAttributes,
 | 
			
		||||
				CreationTime:   fs.CreationTime,
 | 
			
		||||
				LastAccessTime: fs.LastAccessTime,
 | 
			
		||||
				LastWriteTime:  fs.LastWriteTime,
 | 
			
		||||
				FileSizeHigh:   fs.FileSizeHigh,
 | 
			
		||||
				FileSizeLow:    fs.FileSizeLow,
 | 
			
		||||
			}
 | 
			
		||||
			stat.name = v.Name
 | 
			
		||||
			stat.path = path
 | 
			
		||||
			return
 | 
			
		||||
			result[i] = stat
 | 
			
		||||
			//result[i] = newFileStatFromInformation(&info, v.Name, path)
 | 
			
		||||
		}(k, v, i)
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
	wg.Wait()
 | 
			
		||||
	//fmt.Println("finished 2")
 | 
			
		||||
	(*reflect.SliceHeader)(unsafe.Pointer(&result)).Cap = i
 | 
			
		||||
	(*reflect.SliceHeader)(unsafe.Pointer(&result)).Len = i
 | 
			
		||||
	data = nil
 | 
			
		||||
	//data = make(map[win32api.DWORDLONG]FileEntry, 0)
 | 
			
		||||
	runtime.GC()
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getUsnJournalReasonString(reason win32api.DWORD) (s string) {
 | 
			
		||||
	var reasons = []string{
 | 
			
		||||
		"DataOverwrite",       // 0x00000001
 | 
			
		||||
		"DataExtend",          // 0x00000002
 | 
			
		||||
		"DataTruncation",      // 0x00000004
 | 
			
		||||
		"0x00000008",          // 0x00000008
 | 
			
		||||
		"NamedDataOverwrite",  // 0x00000010
 | 
			
		||||
		"NamedDataExtend",     // 0x00000020
 | 
			
		||||
		"NamedDataTruncation", // 0x00000040
 | 
			
		||||
		"0x00000080",          // 0x00000080
 | 
			
		||||
		"FileCreate",          // 0x00000100
 | 
			
		||||
		"FileDelete",          // 0x00000200
 | 
			
		||||
		"PropertyChange",      // 0x00000400
 | 
			
		||||
		"SecurityChange",      // 0x00000800
 | 
			
		||||
		"RenameOldName",       // 0x00001000
 | 
			
		||||
		"RenameNewName",       // 0x00002000
 | 
			
		||||
		"IndexableChange",     // 0x00004000
 | 
			
		||||
		"BasicInfoChange",     // 0x00008000
 | 
			
		||||
		"HardLinkChange",      // 0x00010000
 | 
			
		||||
		"CompressionChange",   // 0x00020000
 | 
			
		||||
		"EncryptionChange",    // 0x00040000
 | 
			
		||||
		"ObjectIdChange",      // 0x00080000
 | 
			
		||||
		"ReparsePointChange",  // 0x00100000
 | 
			
		||||
		"StreamChange",        // 0x00200000
 | 
			
		||||
		"0x00400000",          // 0x00400000
 | 
			
		||||
		"0x00800000",          // 0x00800000
 | 
			
		||||
		"0x01000000",          // 0x01000000
 | 
			
		||||
		"0x02000000",          // 0x02000000
 | 
			
		||||
		"0x04000000",          // 0x04000000
 | 
			
		||||
		"0x08000000",          // 0x08000000
 | 
			
		||||
		"0x10000000",          // 0x10000000
 | 
			
		||||
		"0x20000000",          // 0x20000000
 | 
			
		||||
		"0x40000000",          // 0x40000000
 | 
			
		||||
		"*Close*",             // 0x80000000
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; reason != 0; {
 | 
			
		||||
		if reason&1 == 1 {
 | 
			
		||||
			s = s + ", " + reasons[i]
 | 
			
		||||
		}
 | 
			
		||||
		reason >>= 1
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func MonitorUsnChange(driver string, rec chan FileMonitor) error {
 | 
			
		||||
	pDriver := "\\\\.\\" + driver[:len(driver)-1]
 | 
			
		||||
	fd, err := CreateFile(pDriver, syscall.O_RDONLY, win32api.FILE_ATTRIBUTE_NORMAL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	ujd, _, err := queryUsnJournal(fd)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rujd := win32api.READ_USN_JOURNAL_DATA{ujd.NextUsn, 0xFFFFFFFF, 0, 0, 1, ujd.UsnJournalID}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		var usn win32api.USN
 | 
			
		||||
		data, done, err := readUsnJournal(fd, &rujd)
 | 
			
		||||
		if err != nil || done <= uint32(unsafe.Sizeof(usn)) {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		usn = *(*win32api.USN)(unsafe.Pointer(&data[0]))
 | 
			
		||||
 | 
			
		||||
		var ur *win32api.USN_RECORD
 | 
			
		||||
		for i := unsafe.Sizeof(usn); i < uintptr(done); i += uintptr(ur.RecordLength) {
 | 
			
		||||
			ur = (*win32api.USN_RECORD)(unsafe.Pointer(&data[i]))
 | 
			
		||||
			nameLength := uintptr(ur.FileNameLength) / unsafe.Sizeof(ur.FileName[0])
 | 
			
		||||
			fnp := unsafe.Pointer(&data[i+uintptr(ur.FileNameOffset)])
 | 
			
		||||
			fn := syscall.UTF16ToString((*[10000]uint16)(fnp)[:nameLength])
 | 
			
		||||
			(*reflect.SliceHeader)(unsafe.Pointer(&fn)).Cap = int(nameLength)
 | 
			
		||||
			// fmt.Println("len", ur.FileNameLength, ur.FileNameOffset, "fn", getFullPath(folders, ur.ParentFileReferenceNumber), syscall.UTF16ToString(fn), getUsnJournalReasonString(ur.Reason))
 | 
			
		||||
			typed := uint8(0)
 | 
			
		||||
			if ur.FileAttributes&win32api.FILE_ATTRIBUTE_DIRECTORY != 0 {
 | 
			
		||||
				typed = 1
 | 
			
		||||
			}
 | 
			
		||||
			// fmt.Println("len", ur.FileNameLength, ur.FileNameOffset, "fn", fn)
 | 
			
		||||
			rec <- FileMonitor{Name: fn, Parent: ur.ParentFileReferenceNumber, Type: typed, Self: ur.FileReferenceNumber, Reason: getUsnJournalReasonString(ur.Reason)}
 | 
			
		||||
		}
 | 
			
		||||
		rujd.StartUsn = usn
 | 
			
		||||
		if usn == 0 {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetUsnFileInfo(diskName string, fileMap map[win32api.DWORDLONG]FileEntry, id win32api.DWORDLONG) (FileStat, error) {
 | 
			
		||||
	name := fileMap[id].Name
 | 
			
		||||
	path := GetFullUsnPath(diskName, fileMap, id)
 | 
			
		||||
	fd, err := OpenFileById(diskName, id, syscall.O_RDONLY, win32api.FILE_ATTRIBUTE_NORMAL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return FileStat{}, err
 | 
			
		||||
	}
 | 
			
		||||
	var info syscall.ByHandleFileInformation
 | 
			
		||||
	err = syscall.GetFileInformationByHandle(fd, &info)
 | 
			
		||||
	return newFileStatFromInformation(&info, name, path), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Need a custom Open to work with backup_semantics
 | 
			
		||||
func OpenFileById(diskName string, id win32api.DWORDLONG, mode int, attrs uint32) (syscall.Handle, error) {
 | 
			
		||||
	pDriver := "\\\\.\\" + diskName[:len(diskName)-1]
 | 
			
		||||
	fd, err := CreateFile(pDriver, syscall.O_RDONLY, win32api.FILE_ATTRIBUTE_NORMAL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return syscall.InvalidHandle, err
 | 
			
		||||
	}
 | 
			
		||||
	defer syscall.Close(fd)
 | 
			
		||||
	return OpenFileByIdWithfd(fd, id, mode, attrs)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func OpenFileByIdWithfd(fd syscall.Handle, id win32api.DWORDLONG, mode int, attrs uint32) (syscall.Handle, error) {
 | 
			
		||||
	var access uint32
 | 
			
		||||
	switch mode & (win32api.O_RDONLY | win32api.O_WRONLY | win32api.O_RDWR) {
 | 
			
		||||
	case win32api.O_RDONLY:
 | 
			
		||||
		access = win32api.GENERIC_READ
 | 
			
		||||
	case win32api.O_WRONLY:
 | 
			
		||||
		access = win32api.GENERIC_WRITE
 | 
			
		||||
	case win32api.O_RDWR:
 | 
			
		||||
		access = win32api.GENERIC_READ | win32api.GENERIC_WRITE
 | 
			
		||||
	}
 | 
			
		||||
	if mode&win32api.O_CREAT != 0 {
 | 
			
		||||
		access |= win32api.GENERIC_WRITE
 | 
			
		||||
	}
 | 
			
		||||
	if mode&win32api.O_APPEND != 0 {
 | 
			
		||||
		access &^= win32api.GENERIC_WRITE
 | 
			
		||||
		access |= win32api.FILE_APPEND_DATA
 | 
			
		||||
	}
 | 
			
		||||
	sharemode := uint32(win32api.FILE_SHARE_READ | win32api.FILE_SHARE_WRITE)
 | 
			
		||||
	var sa *syscall.SecurityAttributes
 | 
			
		||||
	if mode&win32api.O_CLOEXEC == 0 {
 | 
			
		||||
		sa = makeInheritSa()
 | 
			
		||||
	}
 | 
			
		||||
	fid := win32api.FILE_ID_DESCRIPTOR{
 | 
			
		||||
		DwSize: 16,
 | 
			
		||||
		Type:   0,
 | 
			
		||||
		FileId: id,
 | 
			
		||||
	}
 | 
			
		||||
	fid.DwSize = win32api.DWORD(unsafe.Sizeof(fid))
 | 
			
		||||
	h, e := win32api.OpenFileById(win32api.HANDLE(fd), &fid, win32api.DWORD(access),
 | 
			
		||||
		win32api.DWORD(sharemode), sa, win32api.DWORD(attrs))
 | 
			
		||||
	return syscall.Handle(h), e
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										262
									
								
								vendor/b612.me/wincmd/permission.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								vendor/b612.me/wincmd/permission.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,262 @@
 | 
			
		||||
package wincmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"b612.me/win32api"
 | 
			
		||||
	"golang.org/x/sys/windows"
 | 
			
		||||
	"golang.org/x/sys/windows/registry"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func StartProcessWithSYS(appPath, cmdLine, workDir string, runas bool) error {
 | 
			
		||||
	var (
 | 
			
		||||
		sessionId          win32api.HANDLE
 | 
			
		||||
		userToken          win32api.TOKEN = 0
 | 
			
		||||
		envInfo            win32api.HANDLE
 | 
			
		||||
		impersonationToken win32api.HANDLE = 0
 | 
			
		||||
		startupInfo        win32api.StartupInfo
 | 
			
		||||
		processInfo        win32api.ProcessInformation
 | 
			
		||||
		sessionInformation win32api.HANDLE              = win32api.HANDLE(0)
 | 
			
		||||
		sessionCount       int                          = 0
 | 
			
		||||
		sessionList        []*win32api.WTS_SESSION_INFO = make([]*win32api.WTS_SESSION_INFO, 0)
 | 
			
		||||
		err                error
 | 
			
		||||
	)
 | 
			
		||||
	if err := win32api.WTSEnumerateSessions(0, 0, 1, &sessionInformation, &sessionCount); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	structSize := unsafe.Sizeof(win32api.WTS_SESSION_INFO{})
 | 
			
		||||
	current := uintptr(sessionInformation)
 | 
			
		||||
	for i := 0; i < sessionCount; i++ {
 | 
			
		||||
		sessionList = append(sessionList, (*win32api.WTS_SESSION_INFO)(unsafe.Pointer(current)))
 | 
			
		||||
		current += structSize
 | 
			
		||||
	}
 | 
			
		||||
	if sessionId, err = func() (win32api.HANDLE, error) {
 | 
			
		||||
		for i := range sessionList {
 | 
			
		||||
			if sessionList[i].State == win32api.WTSActive {
 | 
			
		||||
				return sessionList[i].SessionID, nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if sessionId, err := win32api.WTSGetActiveConsoleSessionId(); sessionId == 0xFFFFFFFF {
 | 
			
		||||
			return 0xFFFFFFFF, fmt.Errorf("get current user session token: call native WTSGetActiveConsoleSessionId: %s", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			return win32api.HANDLE(sessionId), nil
 | 
			
		||||
		}
 | 
			
		||||
	}(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := win32api.WTSQueryUserToken(sessionId, &impersonationToken); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := win32api.DuplicateTokenEx(impersonationToken, 0, 0, int(win32api.SecurityImpersonation), win32api.TokenPrimary, &userToken); err != nil {
 | 
			
		||||
		return fmt.Errorf("call native DuplicateTokenEx: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	if runas {
 | 
			
		||||
		var admin win32api.TOKEN_LINKED_TOKEN
 | 
			
		||||
		var dt uintptr = 0
 | 
			
		||||
		if err := win32api.GetTokenInformation(impersonationToken, 19, uintptr(unsafe.Pointer(&admin)), uintptr(unsafe.Sizeof(admin)), &dt); err == nil {
 | 
			
		||||
			userToken = admin.LinkedToken
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err := win32api.CloseHandle(impersonationToken); err != nil {
 | 
			
		||||
		return fmt.Errorf("close windows handle used for token duplication: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := win32api.CreateEnvironmentBlock(&envInfo, userToken, 0); err != nil {
 | 
			
		||||
		return fmt.Errorf("create environment details for process: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	creationFlags := win32api.CREATE_UNICODE_ENVIRONMENT | win32api.CREATE_NEW_CONSOLE
 | 
			
		||||
	startupInfo.ShowWindow = win32api.SW_SHOW
 | 
			
		||||
	startupInfo.Desktop = windows.StringToUTF16Ptr("winsta0\\default")
 | 
			
		||||
	if err := win32api.CreateProcessAsUser(userToken, appPath, cmdLine, 0, 0, 0,
 | 
			
		||||
		creationFlags, envInfo, workDir, &startupInfo, &processInfo); err != nil {
 | 
			
		||||
		return fmt.Errorf("create process as user: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetRunningProcess() ([]map[string]string, error) {
 | 
			
		||||
	result := []map[string]string{}
 | 
			
		||||
	pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return result, err
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		var proc win32api.PROCESSENTRY32
 | 
			
		||||
		proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc))
 | 
			
		||||
		if err := win32api.Process32Next(pHandle, &proc); err == nil {
 | 
			
		||||
			bytetmp := proc.SzExeFile[0:]
 | 
			
		||||
			var sakura []byte
 | 
			
		||||
			for _, v := range bytetmp {
 | 
			
		||||
				if v == byte(0) {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				sakura = append(sakura, v)
 | 
			
		||||
			}
 | 
			
		||||
			result = append(result, map[string]string{"name": string(sakura), "pid": strconv.Itoa(int(proc.Th32ProcessID)), "ppid": fmt.Sprint(int(proc.Th32ParentProcessID))})
 | 
			
		||||
		} else {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	win32api.CloseHandle(pHandle)
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsProcessRunningByPID(pid int) bool {
 | 
			
		||||
	pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		var proc win32api.PROCESSENTRY32
 | 
			
		||||
		proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc))
 | 
			
		||||
		if err := win32api.Process32Next(pHandle, &proc); err == nil {
 | 
			
		||||
			bytetmp := int(proc.Th32ProcessID)
 | 
			
		||||
			if bytetmp == pid {
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	win32api.CloseHandle(pHandle)
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
func IsProcessRunning(name string) bool {
 | 
			
		||||
	pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		var proc win32api.PROCESSENTRY32
 | 
			
		||||
		proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc))
 | 
			
		||||
		if err := win32api.Process32Next(pHandle, &proc); err == nil {
 | 
			
		||||
			bytetmp := proc.SzExeFile[0:]
 | 
			
		||||
			var sakura []byte
 | 
			
		||||
			for _, v := range bytetmp {
 | 
			
		||||
				if v == byte(0) {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				sakura = append(sakura, v)
 | 
			
		||||
			}
 | 
			
		||||
			if strings.ToLower(strings.TrimSpace(string(sakura))) == strings.ToLower(strings.TrimSpace(name)) {
 | 
			
		||||
				return true
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	win32api.CloseHandle(pHandle)
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func GetProcessCount(name string) int {
 | 
			
		||||
	var res int = 0
 | 
			
		||||
	pHandle, err := win32api.CreateToolhelp32Snapshot(0x2, 0x0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	for {
 | 
			
		||||
		var proc win32api.PROCESSENTRY32
 | 
			
		||||
		proc.DwSize = win32api.Ulong(unsafe.Sizeof(proc))
 | 
			
		||||
		if err := win32api.Process32Next(pHandle, &proc); err == nil {
 | 
			
		||||
			bytetmp := proc.SzExeFile[0:]
 | 
			
		||||
			var sakura []byte
 | 
			
		||||
			for _, v := range bytetmp {
 | 
			
		||||
				if v == byte(0) {
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				sakura = append(sakura, v)
 | 
			
		||||
			}
 | 
			
		||||
			if strings.ToLower(strings.TrimSpace(string(sakura))) == strings.ToLower(strings.TrimSpace(name)) {
 | 
			
		||||
				res++
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	win32api.CloseHandle(pHandle)
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func Isas() bool {
 | 
			
		||||
	_, errs := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM`, registry.ALL_ACCESS)
 | 
			
		||||
	if errs != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StartProcess(appPath, cmdLine, wordDir string, runas bool, ShowWindow int) bool {
 | 
			
		||||
	var cst string
 | 
			
		||||
	if runas {
 | 
			
		||||
		cst = "runas"
 | 
			
		||||
	} else {
 | 
			
		||||
		cst = "open"
 | 
			
		||||
	}
 | 
			
		||||
	r := win32api.ShellExecute(0, cst, appPath, cmdLine, wordDir, ShowWindow)
 | 
			
		||||
	if r != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
func StartProcessWithPID(appPath, cmdLine, workDir string, runas bool, ShowWindow int) int {
 | 
			
		||||
	var sakura win32api.SHELLEXECUTEINFOW
 | 
			
		||||
	sakura.Hwnd = 0
 | 
			
		||||
	sakura.NShow = ShowWindow
 | 
			
		||||
	sakura.FMask = 0x00000040
 | 
			
		||||
	sakura.LpParameters = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(cmdLine)))
 | 
			
		||||
	sakura.LpFile = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(appPath)))
 | 
			
		||||
	sakura.LpDirectory = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(workDir)))
 | 
			
		||||
	if runas {
 | 
			
		||||
		sakura.LpVerb = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("runas")))
 | 
			
		||||
	} else {
 | 
			
		||||
		sakura.LpVerb = uintptr(unsafe.Pointer(windows.StringToUTF16Ptr("open")))
 | 
			
		||||
	}
 | 
			
		||||
	sakura.CbSize = win32api.DWORD(unsafe.Sizeof(sakura))
 | 
			
		||||
 | 
			
		||||
	if err := win32api.ShellExecuteEx(&sakura); err != nil {
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
	return int(win32api.GetProcessId(sakura.HProcess))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func AutoRun(key, path string) (bool, error) {
 | 
			
		||||
	reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS)
 | 
			
		||||
	if errs != nil {
 | 
			
		||||
		return false, errs
 | 
			
		||||
	}
 | 
			
		||||
	if errs = reg.SetStringValue(key, path); errs != nil {
 | 
			
		||||
		return false, errs
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DeleteAutoRun(key string) (bool, error) {
 | 
			
		||||
	reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS)
 | 
			
		||||
	if errs != nil {
 | 
			
		||||
		return false, errs
 | 
			
		||||
	}
 | 
			
		||||
	if _, i, _ := reg.GetStringValue(key); i == 0 {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	if errs = reg.DeleteValue(key); errs != nil {
 | 
			
		||||
		return false, errs
 | 
			
		||||
	}
 | 
			
		||||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsAutoRun(key, path string) bool {
 | 
			
		||||
	reg, errs := registry.OpenKey(registry.LOCAL_MACHINE, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.ALL_ACCESS)
 | 
			
		||||
	if errs != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	if sa, _, _ := reg.GetStringValue(key); sa == path {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										353
									
								
								vendor/b612.me/wincmd/svc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										353
									
								
								vendor/b612.me/wincmd/svc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,353 @@
 | 
			
		||||
package wincmd
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"golang.org/x/sys/windows"
 | 
			
		||||
	"golang.org/x/sys/windows/svc"
 | 
			
		||||
	"golang.org/x/sys/windows/svc/eventlog"
 | 
			
		||||
	"golang.org/x/sys/windows/svc/mgr"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type SvcStatus svc.State
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	Stopped         = SvcStatus(svc.Stopped)
 | 
			
		||||
	StartPending    = SvcStatus(svc.StartPending)
 | 
			
		||||
	StopPending     = SvcStatus(svc.StopPending)
 | 
			
		||||
	Running         = SvcStatus(svc.Running)
 | 
			
		||||
	ContinuePending = SvcStatus(svc.ContinuePending)
 | 
			
		||||
	PausePending    = SvcStatus(svc.PausePending)
 | 
			
		||||
	Paused          = SvcStatus(svc.Paused)
 | 
			
		||||
 | 
			
		||||
	StartManual    = windows.SERVICE_DEMAND_START // the service must be started manually
 | 
			
		||||
	StartAutomatic = windows.SERVICE_AUTO_START   // the service will start by itself whenever the computer reboots
 | 
			
		||||
	StartDisabled  = windows.SERVICE_DISABLED     // the service cannot be started
 | 
			
		||||
 | 
			
		||||
	// The severity of the error, and action taken,
 | 
			
		||||
	// if this service fails to start.
 | 
			
		||||
	ErrorCritical = windows.SERVICE_ERROR_CRITICAL
 | 
			
		||||
	ErrorIgnore   = windows.SERVICE_ERROR_IGNORE
 | 
			
		||||
	ErrorNormal   = windows.SERVICE_ERROR_NORMAL
 | 
			
		||||
	ErrorSevere   = windows.SERVICE_ERROR_SEVERE
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type WinSvcExecute struct {
 | 
			
		||||
	Run         func()
 | 
			
		||||
	Stop        func()
 | 
			
		||||
	Interrupt   func()
 | 
			
		||||
	Pause       func()
 | 
			
		||||
	Continue    func()
 | 
			
		||||
	OtherMethod func(svc.Cmd)
 | 
			
		||||
	Name        string
 | 
			
		||||
	Accepted    []svc.Accepted
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type WinSvcInput struct {
 | 
			
		||||
	Name             string
 | 
			
		||||
	DisplayName      string
 | 
			
		||||
	ExecPath         string
 | 
			
		||||
	DelayedAutoStart bool
 | 
			
		||||
	Description      string
 | 
			
		||||
	StartType        uint32
 | 
			
		||||
	Args             []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type WinSvc struct {
 | 
			
		||||
	*mgr.Service
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func IsServiceExists(name string) (bool, error) {
 | 
			
		||||
	if !Isas() {
 | 
			
		||||
		return false, errors.New("permission deny")
 | 
			
		||||
	}
 | 
			
		||||
	winmgr, err := mgr.Connect()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	defer winmgr.Disconnect()
 | 
			
		||||
	lists, err := winmgr.ListServices()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	for _, v := range lists {
 | 
			
		||||
		if name == v {
 | 
			
		||||
			return true, nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CreateService(mysvc WinSvcInput) (*WinSvc, error) {
 | 
			
		||||
	if !Isas() {
 | 
			
		||||
		return nil, errors.New("permission deny")
 | 
			
		||||
	}
 | 
			
		||||
	if exists, err := IsServiceExists(mysvc.Name); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	} else if exists {
 | 
			
		||||
		return nil, errors.New("service already exists")
 | 
			
		||||
	}
 | 
			
		||||
	winmgr, err := mgr.Connect()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer winmgr.Disconnect()
 | 
			
		||||
	mycfg := mgr.Config{
 | 
			
		||||
		DisplayName:      mysvc.DisplayName,
 | 
			
		||||
		StartType:        mysvc.StartType,
 | 
			
		||||
		DelayedAutoStart: mysvc.DelayedAutoStart,
 | 
			
		||||
		Description:      mysvc.Description,
 | 
			
		||||
	}
 | 
			
		||||
	gsvc, err := winmgr.CreateService(mysvc.Name, mysvc.ExecPath, mycfg, mysvc.Args...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	err = eventlog.InstallAsEventCreate(mysvc.Name, eventlog.Error|eventlog.Warning|eventlog.Info)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		gsvc.Delete()
 | 
			
		||||
		return nil, fmt.Errorf("winsvc.InstallService: InstallAsEventCreate failed, err = %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	var result WinSvc
 | 
			
		||||
	result.Service = gsvc
 | 
			
		||||
	return &result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func OpenService(name string) (*WinSvc, error) {
 | 
			
		||||
	if !Isas() {
 | 
			
		||||
		return nil, errors.New("permission deny")
 | 
			
		||||
	}
 | 
			
		||||
	if exists, err := IsServiceExists(name); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	} else if !exists {
 | 
			
		||||
		return nil, errors.New("service not exists")
 | 
			
		||||
	}
 | 
			
		||||
	winmgr, err := mgr.Connect()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer winmgr.Disconnect()
 | 
			
		||||
	gsvc, err := winmgr.OpenService(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	var result WinSvc
 | 
			
		||||
	result.Service = gsvc
 | 
			
		||||
	return &result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func DeleteService(name string) error {
 | 
			
		||||
	mysvc, err := OpenService(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	err = mysvc.Service.Delete()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		mysvc.Close()
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	mysvc.Close()
 | 
			
		||||
	err = eventlog.Remove(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var count int
 | 
			
		||||
	for {
 | 
			
		||||
		if ok, err := IsServiceExists(name); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		} else if !ok {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		time.Sleep(time.Millisecond * 300)
 | 
			
		||||
		count++
 | 
			
		||||
		if count > 100 {
 | 
			
		||||
			return errors.New("timeout")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StopService(name string) error {
 | 
			
		||||
	mysvc, err := OpenService(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer mysvc.Close()
 | 
			
		||||
	_, err = mysvc.Service.Control(svc.Stop)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var count int
 | 
			
		||||
	for {
 | 
			
		||||
		status, err := mysvc.Service.Query()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if status.State == svc.Stopped {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		time.Sleep(time.Millisecond * 100)
 | 
			
		||||
		count++
 | 
			
		||||
		if count > 100 {
 | 
			
		||||
			return errors.New("timeout")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func StartService(name string) error {
 | 
			
		||||
	mysvc, err := OpenService(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer mysvc.Close()
 | 
			
		||||
	err = mysvc.Service.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var count int
 | 
			
		||||
	for {
 | 
			
		||||
		status, err := mysvc.Service.Query()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if status.State == svc.Running {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		time.Sleep(time.Millisecond * 100)
 | 
			
		||||
		count++
 | 
			
		||||
		if count > 100 {
 | 
			
		||||
			return errors.New("timeout")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ServiceStatus(name string) (SvcStatus, error) {
 | 
			
		||||
	mysvc, err := OpenService(name)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return Stopped, err
 | 
			
		||||
	}
 | 
			
		||||
	defer mysvc.Close()
 | 
			
		||||
	status, err := mysvc.Service.Query()
 | 
			
		||||
	return SvcStatus(status.State), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func InService() (bool, error) {
 | 
			
		||||
	if !Isas() {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	return svc.IsWindowsService()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *WinSvc) Stop() error {
 | 
			
		||||
	return StopService(w.Name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *WinSvc) Delete() error {
 | 
			
		||||
	if err := w.Close(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return DeleteService(w.Name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *WinSvc) StartService() error {
 | 
			
		||||
	err := w.Service.Start()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	var count int
 | 
			
		||||
	for {
 | 
			
		||||
		sts, err := w.Query()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		if SvcStatus(sts.State) == Running {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		time.Sleep(time.Millisecond * 100)
 | 
			
		||||
		count++
 | 
			
		||||
		if count > 100 {
 | 
			
		||||
			return errors.New("timeout")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func InServiceBool() bool {
 | 
			
		||||
	ok, _ := svc.IsWindowsService()
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *WinSvcExecute) Execute(args []string, r <-chan svc.ChangeRequest, s chan<- svc.Status) (svcSpecificEC bool, exitCode uint32) {
 | 
			
		||||
	var sva svc.Accepted
 | 
			
		||||
	alreadyStoped := make(chan int)
 | 
			
		||||
	for _, v := range w.Accepted {
 | 
			
		||||
		sva = sva | v
 | 
			
		||||
	}
 | 
			
		||||
	s <- svc.Status{State: svc.StartPending}
 | 
			
		||||
	go func() {
 | 
			
		||||
		s <- svc.Status{State: svc.Running, Accepts: sva}
 | 
			
		||||
		w.Run()
 | 
			
		||||
		alreadyStoped <- 1
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		select {
 | 
			
		||||
		case <-alreadyStoped:
 | 
			
		||||
			return
 | 
			
		||||
		case c := <-r:
 | 
			
		||||
			switch c.Cmd {
 | 
			
		||||
			case svc.Interrogate:
 | 
			
		||||
				s <- c.CurrentStatus
 | 
			
		||||
				w.Interrupt()
 | 
			
		||||
				s <- c.CurrentStatus
 | 
			
		||||
			case svc.Stop, svc.Shutdown:
 | 
			
		||||
				s <- svc.Status{State: svc.StopPending}
 | 
			
		||||
				w.Stop()
 | 
			
		||||
				s <- svc.Status{State: svc.Stopped}
 | 
			
		||||
				return
 | 
			
		||||
			case svc.Pause:
 | 
			
		||||
				s <- svc.Status{State: svc.PausePending, Accepts: sva}
 | 
			
		||||
				if w.Pause != nil {
 | 
			
		||||
					w.Pause()
 | 
			
		||||
				}
 | 
			
		||||
				s <- svc.Status{State: svc.Paused, Accepts: sva}
 | 
			
		||||
			case svc.Continue:
 | 
			
		||||
				s <- svc.Status{State: svc.ContinuePending, Accepts: sva}
 | 
			
		||||
				if w.Continue != nil {
 | 
			
		||||
					w.Continue()
 | 
			
		||||
				}
 | 
			
		||||
				s <- svc.Status{State: svc.Running, Accepts: sva}
 | 
			
		||||
			default:
 | 
			
		||||
				if w.OtherMethod != nil {
 | 
			
		||||
					w.OtherMethod(c.Cmd)
 | 
			
		||||
				}
 | 
			
		||||
				s <- svc.Status{State: svc.Running, Accepts: sva}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewWinSvcExecute(name string, run, stop func()) *WinSvcExecute {
 | 
			
		||||
	var res WinSvcExecute
 | 
			
		||||
	res.Run = run
 | 
			
		||||
	res.Stop = stop
 | 
			
		||||
	res.Interrupt = func() {
 | 
			
		||||
		time.Sleep(time.Millisecond)
 | 
			
		||||
	}
 | 
			
		||||
	res.Accepted = []svc.Accepted{svc.AcceptStop, svc.AcceptShutdown, svc.AcceptPauseAndContinue}
 | 
			
		||||
	return &res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *WinSvcExecute) StartService() error {
 | 
			
		||||
	return svc.Run(w.Name, w)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *WinSvcExecute) InService() (bool, error) {
 | 
			
		||||
	if !Isas() {
 | 
			
		||||
		return false, nil
 | 
			
		||||
	}
 | 
			
		||||
	return svc.IsWindowsService()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *WinSvcExecute) InServiceBool() bool {
 | 
			
		||||
	ok, _ := svc.IsWindowsService()
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										159
									
								
								vendor/golang.org/x/crypto/blowfish/block.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								vendor/golang.org/x/crypto/blowfish/block.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,159 @@
 | 
			
		||||
// Copyright 2010 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package blowfish
 | 
			
		||||
 | 
			
		||||
// getNextWord returns the next big-endian uint32 value from the byte slice
 | 
			
		||||
// at the given position in a circular manner, updating the position.
 | 
			
		||||
func getNextWord(b []byte, pos *int) uint32 {
 | 
			
		||||
	var w uint32
 | 
			
		||||
	j := *pos
 | 
			
		||||
	for i := 0; i < 4; i++ {
 | 
			
		||||
		w = w<<8 | uint32(b[j])
 | 
			
		||||
		j++
 | 
			
		||||
		if j >= len(b) {
 | 
			
		||||
			j = 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*pos = j
 | 
			
		||||
	return w
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExpandKey performs a key expansion on the given *Cipher. Specifically, it
 | 
			
		||||
// performs the Blowfish algorithm's key schedule which sets up the *Cipher's
 | 
			
		||||
// pi and substitution tables for calls to Encrypt. This is used, primarily,
 | 
			
		||||
// by the bcrypt package to reuse the Blowfish key schedule during its
 | 
			
		||||
// set up. It's unlikely that you need to use this directly.
 | 
			
		||||
func ExpandKey(key []byte, c *Cipher) {
 | 
			
		||||
	j := 0
 | 
			
		||||
	for i := 0; i < 18; i++ {
 | 
			
		||||
		// Using inlined getNextWord for performance.
 | 
			
		||||
		var d uint32
 | 
			
		||||
		for k := 0; k < 4; k++ {
 | 
			
		||||
			d = d<<8 | uint32(key[j])
 | 
			
		||||
			j++
 | 
			
		||||
			if j >= len(key) {
 | 
			
		||||
				j = 0
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		c.p[i] ^= d
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var l, r uint32
 | 
			
		||||
	for i := 0; i < 18; i += 2 {
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.p[i], c.p[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < 256; i += 2 {
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.s0[i], c.s0[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < 256; i += 2 {
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.s1[i], c.s1[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < 256; i += 2 {
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.s2[i], c.s2[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
	for i := 0; i < 256; i += 2 {
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.s3[i], c.s3[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This is similar to ExpandKey, but folds the salt during the key
 | 
			
		||||
// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero
 | 
			
		||||
// salt passed in, reusing ExpandKey turns out to be a place of inefficiency
 | 
			
		||||
// and specializing it here is useful.
 | 
			
		||||
func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) {
 | 
			
		||||
	j := 0
 | 
			
		||||
	for i := 0; i < 18; i++ {
 | 
			
		||||
		c.p[i] ^= getNextWord(key, &j)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	j = 0
 | 
			
		||||
	var l, r uint32
 | 
			
		||||
	for i := 0; i < 18; i += 2 {
 | 
			
		||||
		l ^= getNextWord(salt, &j)
 | 
			
		||||
		r ^= getNextWord(salt, &j)
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.p[i], c.p[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < 256; i += 2 {
 | 
			
		||||
		l ^= getNextWord(salt, &j)
 | 
			
		||||
		r ^= getNextWord(salt, &j)
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.s0[i], c.s0[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < 256; i += 2 {
 | 
			
		||||
		l ^= getNextWord(salt, &j)
 | 
			
		||||
		r ^= getNextWord(salt, &j)
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.s1[i], c.s1[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < 256; i += 2 {
 | 
			
		||||
		l ^= getNextWord(salt, &j)
 | 
			
		||||
		r ^= getNextWord(salt, &j)
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.s2[i], c.s2[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < 256; i += 2 {
 | 
			
		||||
		l ^= getNextWord(salt, &j)
 | 
			
		||||
		r ^= getNextWord(salt, &j)
 | 
			
		||||
		l, r = encryptBlock(l, r, c)
 | 
			
		||||
		c.s3[i], c.s3[i+1] = l, r
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
 | 
			
		||||
	xl, xr := l, r
 | 
			
		||||
	xl ^= c.p[0]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16]
 | 
			
		||||
	xr ^= c.p[17]
 | 
			
		||||
	return xr, xl
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) {
 | 
			
		||||
	xl, xr := l, r
 | 
			
		||||
	xl ^= c.p[17]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3]
 | 
			
		||||
	xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2]
 | 
			
		||||
	xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1]
 | 
			
		||||
	xr ^= c.p[0]
 | 
			
		||||
	return xr, xl
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										99
									
								
								vendor/golang.org/x/crypto/blowfish/cipher.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								vendor/golang.org/x/crypto/blowfish/cipher.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,99 @@
 | 
			
		||||
// Copyright 2010 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm.
 | 
			
		||||
//
 | 
			
		||||
// Blowfish is a legacy cipher and its short block size makes it vulnerable to
 | 
			
		||||
// birthday bound attacks (see https://sweet32.info). It should only be used
 | 
			
		||||
// where compatibility with legacy systems, not security, is the goal.
 | 
			
		||||
//
 | 
			
		||||
// Deprecated: any new system should use AES (from crypto/aes, if necessary in
 | 
			
		||||
// an AEAD mode like crypto/cipher.NewGCM) or XChaCha20-Poly1305 (from
 | 
			
		||||
// golang.org/x/crypto/chacha20poly1305).
 | 
			
		||||
package blowfish // import "golang.org/x/crypto/blowfish"
 | 
			
		||||
 | 
			
		||||
// The code is a port of Bruce Schneier's C implementation.
 | 
			
		||||
// See https://www.schneier.com/blowfish.html.
 | 
			
		||||
 | 
			
		||||
import "strconv"
 | 
			
		||||
 | 
			
		||||
// The Blowfish block size in bytes.
 | 
			
		||||
const BlockSize = 8
 | 
			
		||||
 | 
			
		||||
// A Cipher is an instance of Blowfish encryption using a particular key.
 | 
			
		||||
type Cipher struct {
 | 
			
		||||
	p              [18]uint32
 | 
			
		||||
	s0, s1, s2, s3 [256]uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type KeySizeError int
 | 
			
		||||
 | 
			
		||||
func (k KeySizeError) Error() string {
 | 
			
		||||
	return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCipher creates and returns a Cipher.
 | 
			
		||||
// The key argument should be the Blowfish key, from 1 to 56 bytes.
 | 
			
		||||
func NewCipher(key []byte) (*Cipher, error) {
 | 
			
		||||
	var result Cipher
 | 
			
		||||
	if k := len(key); k < 1 || k > 56 {
 | 
			
		||||
		return nil, KeySizeError(k)
 | 
			
		||||
	}
 | 
			
		||||
	initCipher(&result)
 | 
			
		||||
	ExpandKey(key, &result)
 | 
			
		||||
	return &result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewSaltedCipher creates a returns a Cipher that folds a salt into its key
 | 
			
		||||
// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is
 | 
			
		||||
// sufficient and desirable. For bcrypt compatibility, the key can be over 56
 | 
			
		||||
// bytes.
 | 
			
		||||
func NewSaltedCipher(key, salt []byte) (*Cipher, error) {
 | 
			
		||||
	if len(salt) == 0 {
 | 
			
		||||
		return NewCipher(key)
 | 
			
		||||
	}
 | 
			
		||||
	var result Cipher
 | 
			
		||||
	if k := len(key); k < 1 {
 | 
			
		||||
		return nil, KeySizeError(k)
 | 
			
		||||
	}
 | 
			
		||||
	initCipher(&result)
 | 
			
		||||
	expandKeyWithSalt(key, salt, &result)
 | 
			
		||||
	return &result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BlockSize returns the Blowfish block size, 8 bytes.
 | 
			
		||||
// It is necessary to satisfy the Block interface in the
 | 
			
		||||
// package "crypto/cipher".
 | 
			
		||||
func (c *Cipher) BlockSize() int { return BlockSize }
 | 
			
		||||
 | 
			
		||||
// Encrypt encrypts the 8-byte buffer src using the key k
 | 
			
		||||
// and stores the result in dst.
 | 
			
		||||
// Note that for amounts of data larger than a block,
 | 
			
		||||
// it is not safe to just call Encrypt on successive blocks;
 | 
			
		||||
// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go).
 | 
			
		||||
func (c *Cipher) Encrypt(dst, src []byte) {
 | 
			
		||||
	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
 | 
			
		||||
	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
 | 
			
		||||
	l, r = encryptBlock(l, r, c)
 | 
			
		||||
	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
 | 
			
		||||
	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Decrypt decrypts the 8-byte buffer src using the key k
 | 
			
		||||
// and stores the result in dst.
 | 
			
		||||
func (c *Cipher) Decrypt(dst, src []byte) {
 | 
			
		||||
	l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3])
 | 
			
		||||
	r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7])
 | 
			
		||||
	l, r = decryptBlock(l, r, c)
 | 
			
		||||
	dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l)
 | 
			
		||||
	dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func initCipher(c *Cipher) {
 | 
			
		||||
	copy(c.p[0:], p[0:])
 | 
			
		||||
	copy(c.s0[0:], s0[0:])
 | 
			
		||||
	copy(c.s1[0:], s1[0:])
 | 
			
		||||
	copy(c.s2[0:], s2[0:])
 | 
			
		||||
	copy(c.s3[0:], s3[0:])
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										199
									
								
								vendor/golang.org/x/crypto/blowfish/const.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								vendor/golang.org/x/crypto/blowfish/const.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,199 @@
 | 
			
		||||
// Copyright 2010 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// The startup permutation array and substitution boxes.
 | 
			
		||||
// They are the hexadecimal digits of PI; see:
 | 
			
		||||
// https://www.schneier.com/code/constants.txt.
 | 
			
		||||
 | 
			
		||||
package blowfish
 | 
			
		||||
 | 
			
		||||
var s0 = [256]uint32{
 | 
			
		||||
	0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
 | 
			
		||||
	0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
 | 
			
		||||
	0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
 | 
			
		||||
	0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
 | 
			
		||||
	0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
 | 
			
		||||
	0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
 | 
			
		||||
	0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
 | 
			
		||||
	0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
 | 
			
		||||
	0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
 | 
			
		||||
	0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
 | 
			
		||||
	0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
 | 
			
		||||
	0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
 | 
			
		||||
	0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
 | 
			
		||||
	0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
 | 
			
		||||
	0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
 | 
			
		||||
	0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
 | 
			
		||||
	0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
 | 
			
		||||
	0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
 | 
			
		||||
	0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
 | 
			
		||||
	0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
 | 
			
		||||
	0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
 | 
			
		||||
	0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
 | 
			
		||||
	0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
 | 
			
		||||
	0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
 | 
			
		||||
	0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
 | 
			
		||||
	0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
 | 
			
		||||
	0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
 | 
			
		||||
	0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
 | 
			
		||||
	0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
 | 
			
		||||
	0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
 | 
			
		||||
	0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
 | 
			
		||||
	0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
 | 
			
		||||
	0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
 | 
			
		||||
	0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
 | 
			
		||||
	0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
 | 
			
		||||
	0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
 | 
			
		||||
	0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
 | 
			
		||||
	0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
 | 
			
		||||
	0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
 | 
			
		||||
	0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
 | 
			
		||||
	0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
 | 
			
		||||
	0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
 | 
			
		||||
	0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var s1 = [256]uint32{
 | 
			
		||||
	0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d,
 | 
			
		||||
	0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
 | 
			
		||||
	0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65,
 | 
			
		||||
	0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
 | 
			
		||||
	0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9,
 | 
			
		||||
	0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
 | 
			
		||||
	0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d,
 | 
			
		||||
	0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
 | 
			
		||||
	0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc,
 | 
			
		||||
	0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
 | 
			
		||||
	0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908,
 | 
			
		||||
	0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
 | 
			
		||||
	0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124,
 | 
			
		||||
	0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
 | 
			
		||||
	0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908,
 | 
			
		||||
	0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
 | 
			
		||||
	0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b,
 | 
			
		||||
	0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
 | 
			
		||||
	0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa,
 | 
			
		||||
	0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
 | 
			
		||||
	0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d,
 | 
			
		||||
	0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
 | 
			
		||||
	0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5,
 | 
			
		||||
	0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
 | 
			
		||||
	0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96,
 | 
			
		||||
	0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
 | 
			
		||||
	0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca,
 | 
			
		||||
	0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
 | 
			
		||||
	0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77,
 | 
			
		||||
	0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
 | 
			
		||||
	0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054,
 | 
			
		||||
	0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
 | 
			
		||||
	0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea,
 | 
			
		||||
	0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
 | 
			
		||||
	0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646,
 | 
			
		||||
	0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
 | 
			
		||||
	0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea,
 | 
			
		||||
	0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
 | 
			
		||||
	0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e,
 | 
			
		||||
	0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
 | 
			
		||||
	0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd,
 | 
			
		||||
	0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
 | 
			
		||||
	0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var s2 = [256]uint32{
 | 
			
		||||
	0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7,
 | 
			
		||||
	0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
 | 
			
		||||
	0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af,
 | 
			
		||||
	0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
 | 
			
		||||
	0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4,
 | 
			
		||||
	0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
 | 
			
		||||
	0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec,
 | 
			
		||||
	0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
 | 
			
		||||
	0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332,
 | 
			
		||||
	0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
 | 
			
		||||
	0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58,
 | 
			
		||||
	0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
 | 
			
		||||
	0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22,
 | 
			
		||||
	0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
 | 
			
		||||
	0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60,
 | 
			
		||||
	0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
 | 
			
		||||
	0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99,
 | 
			
		||||
	0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
 | 
			
		||||
	0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74,
 | 
			
		||||
	0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
 | 
			
		||||
	0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3,
 | 
			
		||||
	0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
 | 
			
		||||
	0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979,
 | 
			
		||||
	0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
 | 
			
		||||
	0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa,
 | 
			
		||||
	0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
 | 
			
		||||
	0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086,
 | 
			
		||||
	0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
 | 
			
		||||
	0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24,
 | 
			
		||||
	0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
 | 
			
		||||
	0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84,
 | 
			
		||||
	0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
 | 
			
		||||
	0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09,
 | 
			
		||||
	0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
 | 
			
		||||
	0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe,
 | 
			
		||||
	0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
 | 
			
		||||
	0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0,
 | 
			
		||||
	0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
 | 
			
		||||
	0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188,
 | 
			
		||||
	0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
 | 
			
		||||
	0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8,
 | 
			
		||||
	0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
 | 
			
		||||
	0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var s3 = [256]uint32{
 | 
			
		||||
	0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
 | 
			
		||||
	0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
 | 
			
		||||
	0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
 | 
			
		||||
	0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
 | 
			
		||||
	0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
 | 
			
		||||
	0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
 | 
			
		||||
	0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
 | 
			
		||||
	0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
 | 
			
		||||
	0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
 | 
			
		||||
	0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
 | 
			
		||||
	0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
 | 
			
		||||
	0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
 | 
			
		||||
	0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
 | 
			
		||||
	0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
 | 
			
		||||
	0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
 | 
			
		||||
	0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
 | 
			
		||||
	0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
 | 
			
		||||
	0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
 | 
			
		||||
	0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
 | 
			
		||||
	0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
 | 
			
		||||
	0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
 | 
			
		||||
	0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
 | 
			
		||||
	0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
 | 
			
		||||
	0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
 | 
			
		||||
	0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
 | 
			
		||||
	0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
 | 
			
		||||
	0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
 | 
			
		||||
	0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
 | 
			
		||||
	0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
 | 
			
		||||
	0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
 | 
			
		||||
	0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
 | 
			
		||||
	0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
 | 
			
		||||
	0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
 | 
			
		||||
	0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
 | 
			
		||||
	0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
 | 
			
		||||
	0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
 | 
			
		||||
	0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
 | 
			
		||||
	0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
 | 
			
		||||
	0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
 | 
			
		||||
	0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
 | 
			
		||||
	0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
 | 
			
		||||
	0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
 | 
			
		||||
	0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var p = [18]uint32{
 | 
			
		||||
	0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
 | 
			
		||||
	0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
 | 
			
		||||
	0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_arm64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
// Copyright 2018 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build go1.11 && gc && !purego
 | 
			
		||||
// +build go1.11,gc,!purego
 | 
			
		||||
 | 
			
		||||
package chacha20
 | 
			
		||||
 | 
			
		||||
const bufSize = 256
 | 
			
		||||
 | 
			
		||||
//go:noescape
 | 
			
		||||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
 | 
			
		||||
 | 
			
		||||
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
 | 
			
		||||
	xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										398
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										398
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,398 @@
 | 
			
		||||
// Copyright 2016 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package chacha20 implements the ChaCha20 and XChaCha20 encryption algorithms
 | 
			
		||||
// as specified in RFC 8439 and draft-irtf-cfrg-xchacha-01.
 | 
			
		||||
package chacha20
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/cipher"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"math/bits"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/internal/subtle"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// KeySize is the size of the key used by this cipher, in bytes.
 | 
			
		||||
	KeySize = 32
 | 
			
		||||
 | 
			
		||||
	// NonceSize is the size of the nonce used with the standard variant of this
 | 
			
		||||
	// cipher, in bytes.
 | 
			
		||||
	//
 | 
			
		||||
	// Note that this is too short to be safely generated at random if the same
 | 
			
		||||
	// key is reused more than 2³² times.
 | 
			
		||||
	NonceSize = 12
 | 
			
		||||
 | 
			
		||||
	// NonceSizeX is the size of the nonce used with the XChaCha20 variant of
 | 
			
		||||
	// this cipher, in bytes.
 | 
			
		||||
	NonceSizeX = 24
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Cipher is a stateful instance of ChaCha20 or XChaCha20 using a particular key
 | 
			
		||||
// and nonce. A *Cipher implements the cipher.Stream interface.
 | 
			
		||||
type Cipher struct {
 | 
			
		||||
	// The ChaCha20 state is 16 words: 4 constant, 8 of key, 1 of counter
 | 
			
		||||
	// (incremented after each block), and 3 of nonce.
 | 
			
		||||
	key     [8]uint32
 | 
			
		||||
	counter uint32
 | 
			
		||||
	nonce   [3]uint32
 | 
			
		||||
 | 
			
		||||
	// The last len bytes of buf are leftover key stream bytes from the previous
 | 
			
		||||
	// XORKeyStream invocation. The size of buf depends on how many blocks are
 | 
			
		||||
	// computed at a time by xorKeyStreamBlocks.
 | 
			
		||||
	buf [bufSize]byte
 | 
			
		||||
	len int
 | 
			
		||||
 | 
			
		||||
	// overflow is set when the counter overflowed, no more blocks can be
 | 
			
		||||
	// generated, and the next XORKeyStream call should panic.
 | 
			
		||||
	overflow bool
 | 
			
		||||
 | 
			
		||||
	// The counter-independent results of the first round are cached after they
 | 
			
		||||
	// are computed the first time.
 | 
			
		||||
	precompDone      bool
 | 
			
		||||
	p1, p5, p9, p13  uint32
 | 
			
		||||
	p2, p6, p10, p14 uint32
 | 
			
		||||
	p3, p7, p11, p15 uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ cipher.Stream = (*Cipher)(nil)
 | 
			
		||||
 | 
			
		||||
// NewUnauthenticatedCipher creates a new ChaCha20 stream cipher with the given
 | 
			
		||||
// 32 bytes key and a 12 or 24 bytes nonce. If a nonce of 24 bytes is provided,
 | 
			
		||||
// the XChaCha20 construction will be used. It returns an error if key or nonce
 | 
			
		||||
// have any other length.
 | 
			
		||||
//
 | 
			
		||||
// Note that ChaCha20, like all stream ciphers, is not authenticated and allows
 | 
			
		||||
// attackers to silently tamper with the plaintext. For this reason, it is more
 | 
			
		||||
// appropriate as a building block than as a standalone encryption mechanism.
 | 
			
		||||
// Instead, consider using package golang.org/x/crypto/chacha20poly1305.
 | 
			
		||||
func NewUnauthenticatedCipher(key, nonce []byte) (*Cipher, error) {
 | 
			
		||||
	// This function is split into a wrapper so that the Cipher allocation will
 | 
			
		||||
	// be inlined, and depending on how the caller uses the return value, won't
 | 
			
		||||
	// escape to the heap.
 | 
			
		||||
	c := &Cipher{}
 | 
			
		||||
	return newUnauthenticatedCipher(c, key, nonce)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newUnauthenticatedCipher(c *Cipher, key, nonce []byte) (*Cipher, error) {
 | 
			
		||||
	if len(key) != KeySize {
 | 
			
		||||
		return nil, errors.New("chacha20: wrong key size")
 | 
			
		||||
	}
 | 
			
		||||
	if len(nonce) == NonceSizeX {
 | 
			
		||||
		// XChaCha20 uses the ChaCha20 core to mix 16 bytes of the nonce into a
 | 
			
		||||
		// derived key, allowing it to operate on a nonce of 24 bytes. See
 | 
			
		||||
		// draft-irtf-cfrg-xchacha-01, Section 2.3.
 | 
			
		||||
		key, _ = HChaCha20(key, nonce[0:16])
 | 
			
		||||
		cNonce := make([]byte, NonceSize)
 | 
			
		||||
		copy(cNonce[4:12], nonce[16:24])
 | 
			
		||||
		nonce = cNonce
 | 
			
		||||
	} else if len(nonce) != NonceSize {
 | 
			
		||||
		return nil, errors.New("chacha20: wrong nonce size")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	key, nonce = key[:KeySize], nonce[:NonceSize] // bounds check elimination hint
 | 
			
		||||
	c.key = [8]uint32{
 | 
			
		||||
		binary.LittleEndian.Uint32(key[0:4]),
 | 
			
		||||
		binary.LittleEndian.Uint32(key[4:8]),
 | 
			
		||||
		binary.LittleEndian.Uint32(key[8:12]),
 | 
			
		||||
		binary.LittleEndian.Uint32(key[12:16]),
 | 
			
		||||
		binary.LittleEndian.Uint32(key[16:20]),
 | 
			
		||||
		binary.LittleEndian.Uint32(key[20:24]),
 | 
			
		||||
		binary.LittleEndian.Uint32(key[24:28]),
 | 
			
		||||
		binary.LittleEndian.Uint32(key[28:32]),
 | 
			
		||||
	}
 | 
			
		||||
	c.nonce = [3]uint32{
 | 
			
		||||
		binary.LittleEndian.Uint32(nonce[0:4]),
 | 
			
		||||
		binary.LittleEndian.Uint32(nonce[4:8]),
 | 
			
		||||
		binary.LittleEndian.Uint32(nonce[8:12]),
 | 
			
		||||
	}
 | 
			
		||||
	return c, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The constant first 4 words of the ChaCha20 state.
 | 
			
		||||
const (
 | 
			
		||||
	j0 uint32 = 0x61707865 // expa
 | 
			
		||||
	j1 uint32 = 0x3320646e // nd 3
 | 
			
		||||
	j2 uint32 = 0x79622d32 // 2-by
 | 
			
		||||
	j3 uint32 = 0x6b206574 // te k
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const blockSize = 64
 | 
			
		||||
 | 
			
		||||
// quarterRound is the core of ChaCha20. It shuffles the bits of 4 state words.
 | 
			
		||||
// It's executed 4 times for each of the 20 ChaCha20 rounds, operating on all 16
 | 
			
		||||
// words each round, in columnar or diagonal groups of 4 at a time.
 | 
			
		||||
func quarterRound(a, b, c, d uint32) (uint32, uint32, uint32, uint32) {
 | 
			
		||||
	a += b
 | 
			
		||||
	d ^= a
 | 
			
		||||
	d = bits.RotateLeft32(d, 16)
 | 
			
		||||
	c += d
 | 
			
		||||
	b ^= c
 | 
			
		||||
	b = bits.RotateLeft32(b, 12)
 | 
			
		||||
	a += b
 | 
			
		||||
	d ^= a
 | 
			
		||||
	d = bits.RotateLeft32(d, 8)
 | 
			
		||||
	c += d
 | 
			
		||||
	b ^= c
 | 
			
		||||
	b = bits.RotateLeft32(b, 7)
 | 
			
		||||
	return a, b, c, d
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetCounter sets the Cipher counter. The next invocation of XORKeyStream will
 | 
			
		||||
// behave as if (64 * counter) bytes had been encrypted so far.
 | 
			
		||||
//
 | 
			
		||||
// To prevent accidental counter reuse, SetCounter panics if counter is less
 | 
			
		||||
// than the current value.
 | 
			
		||||
//
 | 
			
		||||
// Note that the execution time of XORKeyStream is not independent of the
 | 
			
		||||
// counter value.
 | 
			
		||||
func (s *Cipher) SetCounter(counter uint32) {
 | 
			
		||||
	// Internally, s may buffer multiple blocks, which complicates this
 | 
			
		||||
	// implementation slightly. When checking whether the counter has rolled
 | 
			
		||||
	// back, we must use both s.counter and s.len to determine how many blocks
 | 
			
		||||
	// we have already output.
 | 
			
		||||
	outputCounter := s.counter - uint32(s.len)/blockSize
 | 
			
		||||
	if s.overflow || counter < outputCounter {
 | 
			
		||||
		panic("chacha20: SetCounter attempted to rollback counter")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// In the general case, we set the new counter value and reset s.len to 0,
 | 
			
		||||
	// causing the next call to XORKeyStream to refill the buffer. However, if
 | 
			
		||||
	// we're advancing within the existing buffer, we can save work by simply
 | 
			
		||||
	// setting s.len.
 | 
			
		||||
	if counter < s.counter {
 | 
			
		||||
		s.len = int(s.counter-counter) * blockSize
 | 
			
		||||
	} else {
 | 
			
		||||
		s.counter = counter
 | 
			
		||||
		s.len = 0
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// XORKeyStream XORs each byte in the given slice with a byte from the
 | 
			
		||||
// cipher's key stream. Dst and src must overlap entirely or not at all.
 | 
			
		||||
//
 | 
			
		||||
// If len(dst) < len(src), XORKeyStream will panic. It is acceptable
 | 
			
		||||
// to pass a dst bigger than src, and in that case, XORKeyStream will
 | 
			
		||||
// only update dst[:len(src)] and will not touch the rest of dst.
 | 
			
		||||
//
 | 
			
		||||
// Multiple calls to XORKeyStream behave as if the concatenation of
 | 
			
		||||
// the src buffers was passed in a single run. That is, Cipher
 | 
			
		||||
// maintains state and does not reset at each XORKeyStream call.
 | 
			
		||||
func (s *Cipher) XORKeyStream(dst, src []byte) {
 | 
			
		||||
	if len(src) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if len(dst) < len(src) {
 | 
			
		||||
		panic("chacha20: output smaller than input")
 | 
			
		||||
	}
 | 
			
		||||
	dst = dst[:len(src)]
 | 
			
		||||
	if subtle.InexactOverlap(dst, src) {
 | 
			
		||||
		panic("chacha20: invalid buffer overlap")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// First, drain any remaining key stream from a previous XORKeyStream.
 | 
			
		||||
	if s.len != 0 {
 | 
			
		||||
		keyStream := s.buf[bufSize-s.len:]
 | 
			
		||||
		if len(src) < len(keyStream) {
 | 
			
		||||
			keyStream = keyStream[:len(src)]
 | 
			
		||||
		}
 | 
			
		||||
		_ = src[len(keyStream)-1] // bounds check elimination hint
 | 
			
		||||
		for i, b := range keyStream {
 | 
			
		||||
			dst[i] = src[i] ^ b
 | 
			
		||||
		}
 | 
			
		||||
		s.len -= len(keyStream)
 | 
			
		||||
		dst, src = dst[len(keyStream):], src[len(keyStream):]
 | 
			
		||||
	}
 | 
			
		||||
	if len(src) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we'd need to let the counter overflow and keep generating output,
 | 
			
		||||
	// panic immediately. If instead we'd only reach the last block, remember
 | 
			
		||||
	// not to generate any more output after the buffer is drained.
 | 
			
		||||
	numBlocks := (uint64(len(src)) + blockSize - 1) / blockSize
 | 
			
		||||
	if s.overflow || uint64(s.counter)+numBlocks > 1<<32 {
 | 
			
		||||
		panic("chacha20: counter overflow")
 | 
			
		||||
	} else if uint64(s.counter)+numBlocks == 1<<32 {
 | 
			
		||||
		s.overflow = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// xorKeyStreamBlocks implementations expect input lengths that are a
 | 
			
		||||
	// multiple of bufSize. Platform-specific ones process multiple blocks at a
 | 
			
		||||
	// time, so have bufSizes that are a multiple of blockSize.
 | 
			
		||||
 | 
			
		||||
	full := len(src) - len(src)%bufSize
 | 
			
		||||
	if full > 0 {
 | 
			
		||||
		s.xorKeyStreamBlocks(dst[:full], src[:full])
 | 
			
		||||
	}
 | 
			
		||||
	dst, src = dst[full:], src[full:]
 | 
			
		||||
 | 
			
		||||
	// If using a multi-block xorKeyStreamBlocks would overflow, use the generic
 | 
			
		||||
	// one that does one block at a time.
 | 
			
		||||
	const blocksPerBuf = bufSize / blockSize
 | 
			
		||||
	if uint64(s.counter)+blocksPerBuf > 1<<32 {
 | 
			
		||||
		s.buf = [bufSize]byte{}
 | 
			
		||||
		numBlocks := (len(src) + blockSize - 1) / blockSize
 | 
			
		||||
		buf := s.buf[bufSize-numBlocks*blockSize:]
 | 
			
		||||
		copy(buf, src)
 | 
			
		||||
		s.xorKeyStreamBlocksGeneric(buf, buf)
 | 
			
		||||
		s.len = len(buf) - copy(dst, buf)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we have a partial (multi-)block, pad it for xorKeyStreamBlocks, and
 | 
			
		||||
	// keep the leftover keystream for the next XORKeyStream invocation.
 | 
			
		||||
	if len(src) > 0 {
 | 
			
		||||
		s.buf = [bufSize]byte{}
 | 
			
		||||
		copy(s.buf[:], src)
 | 
			
		||||
		s.xorKeyStreamBlocks(s.buf[:], s.buf[:])
 | 
			
		||||
		s.len = bufSize - copy(dst, s.buf[:])
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Cipher) xorKeyStreamBlocksGeneric(dst, src []byte) {
 | 
			
		||||
	if len(dst) != len(src) || len(dst)%blockSize != 0 {
 | 
			
		||||
		panic("chacha20: internal error: wrong dst and/or src length")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// To generate each block of key stream, the initial cipher state
 | 
			
		||||
	// (represented below) is passed through 20 rounds of shuffling,
 | 
			
		||||
	// alternatively applying quarterRounds by columns (like 1, 5, 9, 13)
 | 
			
		||||
	// or by diagonals (like 1, 6, 11, 12).
 | 
			
		||||
	//
 | 
			
		||||
	//      0:cccccccc   1:cccccccc   2:cccccccc   3:cccccccc
 | 
			
		||||
	//      4:kkkkkkkk   5:kkkkkkkk   6:kkkkkkkk   7:kkkkkkkk
 | 
			
		||||
	//      8:kkkkkkkk   9:kkkkkkkk  10:kkkkkkkk  11:kkkkkkkk
 | 
			
		||||
	//     12:bbbbbbbb  13:nnnnnnnn  14:nnnnnnnn  15:nnnnnnnn
 | 
			
		||||
	//
 | 
			
		||||
	//            c=constant k=key b=blockcount n=nonce
 | 
			
		||||
	var (
 | 
			
		||||
		c0, c1, c2, c3   = j0, j1, j2, j3
 | 
			
		||||
		c4, c5, c6, c7   = s.key[0], s.key[1], s.key[2], s.key[3]
 | 
			
		||||
		c8, c9, c10, c11 = s.key[4], s.key[5], s.key[6], s.key[7]
 | 
			
		||||
		_, c13, c14, c15 = s.counter, s.nonce[0], s.nonce[1], s.nonce[2]
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// Three quarters of the first round don't depend on the counter, so we can
 | 
			
		||||
	// calculate them here, and reuse them for multiple blocks in the loop, and
 | 
			
		||||
	// for future XORKeyStream invocations.
 | 
			
		||||
	if !s.precompDone {
 | 
			
		||||
		s.p1, s.p5, s.p9, s.p13 = quarterRound(c1, c5, c9, c13)
 | 
			
		||||
		s.p2, s.p6, s.p10, s.p14 = quarterRound(c2, c6, c10, c14)
 | 
			
		||||
		s.p3, s.p7, s.p11, s.p15 = quarterRound(c3, c7, c11, c15)
 | 
			
		||||
		s.precompDone = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// A condition of len(src) > 0 would be sufficient, but this also
 | 
			
		||||
	// acts as a bounds check elimination hint.
 | 
			
		||||
	for len(src) >= 64 && len(dst) >= 64 {
 | 
			
		||||
		// The remainder of the first column round.
 | 
			
		||||
		fcr0, fcr4, fcr8, fcr12 := quarterRound(c0, c4, c8, s.counter)
 | 
			
		||||
 | 
			
		||||
		// The second diagonal round.
 | 
			
		||||
		x0, x5, x10, x15 := quarterRound(fcr0, s.p5, s.p10, s.p15)
 | 
			
		||||
		x1, x6, x11, x12 := quarterRound(s.p1, s.p6, s.p11, fcr12)
 | 
			
		||||
		x2, x7, x8, x13 := quarterRound(s.p2, s.p7, fcr8, s.p13)
 | 
			
		||||
		x3, x4, x9, x14 := quarterRound(s.p3, fcr4, s.p9, s.p14)
 | 
			
		||||
 | 
			
		||||
		// The remaining 18 rounds.
 | 
			
		||||
		for i := 0; i < 9; i++ {
 | 
			
		||||
			// Column round.
 | 
			
		||||
			x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
 | 
			
		||||
			x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
 | 
			
		||||
			x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
 | 
			
		||||
			x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
 | 
			
		||||
 | 
			
		||||
			// Diagonal round.
 | 
			
		||||
			x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
 | 
			
		||||
			x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
 | 
			
		||||
			x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
 | 
			
		||||
			x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Add back the initial state to generate the key stream, then
 | 
			
		||||
		// XOR the key stream with the source and write out the result.
 | 
			
		||||
		addXor(dst[0:4], src[0:4], x0, c0)
 | 
			
		||||
		addXor(dst[4:8], src[4:8], x1, c1)
 | 
			
		||||
		addXor(dst[8:12], src[8:12], x2, c2)
 | 
			
		||||
		addXor(dst[12:16], src[12:16], x3, c3)
 | 
			
		||||
		addXor(dst[16:20], src[16:20], x4, c4)
 | 
			
		||||
		addXor(dst[20:24], src[20:24], x5, c5)
 | 
			
		||||
		addXor(dst[24:28], src[24:28], x6, c6)
 | 
			
		||||
		addXor(dst[28:32], src[28:32], x7, c7)
 | 
			
		||||
		addXor(dst[32:36], src[32:36], x8, c8)
 | 
			
		||||
		addXor(dst[36:40], src[36:40], x9, c9)
 | 
			
		||||
		addXor(dst[40:44], src[40:44], x10, c10)
 | 
			
		||||
		addXor(dst[44:48], src[44:48], x11, c11)
 | 
			
		||||
		addXor(dst[48:52], src[48:52], x12, s.counter)
 | 
			
		||||
		addXor(dst[52:56], src[52:56], x13, c13)
 | 
			
		||||
		addXor(dst[56:60], src[56:60], x14, c14)
 | 
			
		||||
		addXor(dst[60:64], src[60:64], x15, c15)
 | 
			
		||||
 | 
			
		||||
		s.counter += 1
 | 
			
		||||
 | 
			
		||||
		src, dst = src[blockSize:], dst[blockSize:]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HChaCha20 uses the ChaCha20 core to generate a derived key from a 32 bytes
 | 
			
		||||
// key and a 16 bytes nonce. It returns an error if key or nonce have any other
 | 
			
		||||
// length. It is used as part of the XChaCha20 construction.
 | 
			
		||||
func HChaCha20(key, nonce []byte) ([]byte, error) {
 | 
			
		||||
	// This function is split into a wrapper so that the slice allocation will
 | 
			
		||||
	// be inlined, and depending on how the caller uses the return value, won't
 | 
			
		||||
	// escape to the heap.
 | 
			
		||||
	out := make([]byte, 32)
 | 
			
		||||
	return hChaCha20(out, key, nonce)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hChaCha20(out, key, nonce []byte) ([]byte, error) {
 | 
			
		||||
	if len(key) != KeySize {
 | 
			
		||||
		return nil, errors.New("chacha20: wrong HChaCha20 key size")
 | 
			
		||||
	}
 | 
			
		||||
	if len(nonce) != 16 {
 | 
			
		||||
		return nil, errors.New("chacha20: wrong HChaCha20 nonce size")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	x0, x1, x2, x3 := j0, j1, j2, j3
 | 
			
		||||
	x4 := binary.LittleEndian.Uint32(key[0:4])
 | 
			
		||||
	x5 := binary.LittleEndian.Uint32(key[4:8])
 | 
			
		||||
	x6 := binary.LittleEndian.Uint32(key[8:12])
 | 
			
		||||
	x7 := binary.LittleEndian.Uint32(key[12:16])
 | 
			
		||||
	x8 := binary.LittleEndian.Uint32(key[16:20])
 | 
			
		||||
	x9 := binary.LittleEndian.Uint32(key[20:24])
 | 
			
		||||
	x10 := binary.LittleEndian.Uint32(key[24:28])
 | 
			
		||||
	x11 := binary.LittleEndian.Uint32(key[28:32])
 | 
			
		||||
	x12 := binary.LittleEndian.Uint32(nonce[0:4])
 | 
			
		||||
	x13 := binary.LittleEndian.Uint32(nonce[4:8])
 | 
			
		||||
	x14 := binary.LittleEndian.Uint32(nonce[8:12])
 | 
			
		||||
	x15 := binary.LittleEndian.Uint32(nonce[12:16])
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < 10; i++ {
 | 
			
		||||
		// Diagonal round.
 | 
			
		||||
		x0, x4, x8, x12 = quarterRound(x0, x4, x8, x12)
 | 
			
		||||
		x1, x5, x9, x13 = quarterRound(x1, x5, x9, x13)
 | 
			
		||||
		x2, x6, x10, x14 = quarterRound(x2, x6, x10, x14)
 | 
			
		||||
		x3, x7, x11, x15 = quarterRound(x3, x7, x11, x15)
 | 
			
		||||
 | 
			
		||||
		// Column round.
 | 
			
		||||
		x0, x5, x10, x15 = quarterRound(x0, x5, x10, x15)
 | 
			
		||||
		x1, x6, x11, x12 = quarterRound(x1, x6, x11, x12)
 | 
			
		||||
		x2, x7, x8, x13 = quarterRound(x2, x7, x8, x13)
 | 
			
		||||
		x3, x4, x9, x14 = quarterRound(x3, x4, x9, x14)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = out[31] // bounds check elimination hint
 | 
			
		||||
	binary.LittleEndian.PutUint32(out[0:4], x0)
 | 
			
		||||
	binary.LittleEndian.PutUint32(out[4:8], x1)
 | 
			
		||||
	binary.LittleEndian.PutUint32(out[8:12], x2)
 | 
			
		||||
	binary.LittleEndian.PutUint32(out[12:16], x3)
 | 
			
		||||
	binary.LittleEndian.PutUint32(out[16:20], x12)
 | 
			
		||||
	binary.LittleEndian.PutUint32(out[20:24], x13)
 | 
			
		||||
	binary.LittleEndian.PutUint32(out[24:28], x14)
 | 
			
		||||
	binary.LittleEndian.PutUint32(out[28:32], x15)
 | 
			
		||||
	return out, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_noasm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
// Copyright 2018 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build (!arm64 && !s390x && !ppc64le) || (arm64 && !go1.11) || !gc || purego
 | 
			
		||||
// +build !arm64,!s390x,!ppc64le arm64,!go1.11 !gc purego
 | 
			
		||||
 | 
			
		||||
package chacha20
 | 
			
		||||
 | 
			
		||||
const bufSize = blockSize
 | 
			
		||||
 | 
			
		||||
func (s *Cipher) xorKeyStreamBlocks(dst, src []byte) {
 | 
			
		||||
	s.xorKeyStreamBlocksGeneric(dst, src)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										17
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_ppc64le.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
// Copyright 2019 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build gc && !purego
 | 
			
		||||
// +build gc,!purego
 | 
			
		||||
 | 
			
		||||
package chacha20
 | 
			
		||||
 | 
			
		||||
const bufSize = 256
 | 
			
		||||
 | 
			
		||||
//go:noescape
 | 
			
		||||
func chaCha20_ctr32_vsx(out, inp *byte, len int, key *[8]uint32, counter *uint32)
 | 
			
		||||
 | 
			
		||||
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
 | 
			
		||||
	chaCha20_ctr32_vsx(&dst[0], &src[0], len(src), &c.key, &c.counter)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								vendor/golang.org/x/crypto/chacha20/chacha_s390x.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
// Copyright 2018 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build gc && !purego
 | 
			
		||||
// +build gc,!purego
 | 
			
		||||
 | 
			
		||||
package chacha20
 | 
			
		||||
 | 
			
		||||
import "golang.org/x/sys/cpu"
 | 
			
		||||
 | 
			
		||||
var haveAsm = cpu.S390X.HasVX
 | 
			
		||||
 | 
			
		||||
const bufSize = 256
 | 
			
		||||
 | 
			
		||||
// xorKeyStreamVX is an assembly implementation of XORKeyStream. It must only
 | 
			
		||||
// be called when the vector facility is available. Implementation in asm_s390x.s.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func xorKeyStreamVX(dst, src []byte, key *[8]uint32, nonce *[3]uint32, counter *uint32)
 | 
			
		||||
 | 
			
		||||
func (c *Cipher) xorKeyStreamBlocks(dst, src []byte) {
 | 
			
		||||
	if cpu.S390X.HasVX {
 | 
			
		||||
		xorKeyStreamVX(dst, src, &c.key, &c.nonce, &c.counter)
 | 
			
		||||
	} else {
 | 
			
		||||
		c.xorKeyStreamBlocksGeneric(dst, src)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/golang.org/x/crypto/chacha20/xor.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/golang.org/x/crypto/chacha20/xor.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
// Copyright 2018 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found src the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package chacha20
 | 
			
		||||
 | 
			
		||||
import "runtime"
 | 
			
		||||
 | 
			
		||||
// Platforms that have fast unaligned 32-bit little endian accesses.
 | 
			
		||||
const unaligned = runtime.GOARCH == "386" ||
 | 
			
		||||
	runtime.GOARCH == "amd64" ||
 | 
			
		||||
	runtime.GOARCH == "arm64" ||
 | 
			
		||||
	runtime.GOARCH == "ppc64le" ||
 | 
			
		||||
	runtime.GOARCH == "s390x"
 | 
			
		||||
 | 
			
		||||
// addXor reads a little endian uint32 from src, XORs it with (a + b) and
 | 
			
		||||
// places the result in little endian byte order in dst.
 | 
			
		||||
func addXor(dst, src []byte, a, b uint32) {
 | 
			
		||||
	_, _ = src[3], dst[3] // bounds check elimination hint
 | 
			
		||||
	if unaligned {
 | 
			
		||||
		// The compiler should optimize this code into
 | 
			
		||||
		// 32-bit unaligned little endian loads and stores.
 | 
			
		||||
		// TODO: delete once the compiler does a reliably
 | 
			
		||||
		// good job with the generic code below.
 | 
			
		||||
		// See issue #25111 for more details.
 | 
			
		||||
		v := uint32(src[0])
 | 
			
		||||
		v |= uint32(src[1]) << 8
 | 
			
		||||
		v |= uint32(src[2]) << 16
 | 
			
		||||
		v |= uint32(src[3]) << 24
 | 
			
		||||
		v ^= a + b
 | 
			
		||||
		dst[0] = byte(v)
 | 
			
		||||
		dst[1] = byte(v >> 8)
 | 
			
		||||
		dst[2] = byte(v >> 16)
 | 
			
		||||
		dst[3] = byte(v >> 24)
 | 
			
		||||
	} else {
 | 
			
		||||
		a += b
 | 
			
		||||
		dst[0] = src[0] ^ byte(a)
 | 
			
		||||
		dst[1] = src[1] ^ byte(a>>8)
 | 
			
		||||
		dst[2] = src[2] ^ byte(a>>16)
 | 
			
		||||
		dst[3] = src[3] ^ byte(a>>24)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										145
									
								
								vendor/golang.org/x/crypto/curve25519/curve25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								vendor/golang.org/x/crypto/curve25519/curve25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,145 @@
 | 
			
		||||
// Copyright 2019 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package curve25519 provides an implementation of the X25519 function, which
 | 
			
		||||
// performs scalar multiplication on the elliptic curve known as Curve25519.
 | 
			
		||||
// See RFC 7748.
 | 
			
		||||
package curve25519 // import "golang.org/x/crypto/curve25519"
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/subtle"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"golang.org/x/crypto/curve25519/internal/field"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ScalarMult sets dst to the product scalar * point.
 | 
			
		||||
//
 | 
			
		||||
// Deprecated: when provided a low-order point, ScalarMult will set dst to all
 | 
			
		||||
// zeroes, irrespective of the scalar. Instead, use the X25519 function, which
 | 
			
		||||
// will return an error.
 | 
			
		||||
func ScalarMult(dst, scalar, point *[32]byte) {
 | 
			
		||||
	var e [32]byte
 | 
			
		||||
 | 
			
		||||
	copy(e[:], scalar[:])
 | 
			
		||||
	e[0] &= 248
 | 
			
		||||
	e[31] &= 127
 | 
			
		||||
	e[31] |= 64
 | 
			
		||||
 | 
			
		||||
	var x1, x2, z2, x3, z3, tmp0, tmp1 field.Element
 | 
			
		||||
	x1.SetBytes(point[:])
 | 
			
		||||
	x2.One()
 | 
			
		||||
	x3.Set(&x1)
 | 
			
		||||
	z3.One()
 | 
			
		||||
 | 
			
		||||
	swap := 0
 | 
			
		||||
	for pos := 254; pos >= 0; pos-- {
 | 
			
		||||
		b := e[pos/8] >> uint(pos&7)
 | 
			
		||||
		b &= 1
 | 
			
		||||
		swap ^= int(b)
 | 
			
		||||
		x2.Swap(&x3, swap)
 | 
			
		||||
		z2.Swap(&z3, swap)
 | 
			
		||||
		swap = int(b)
 | 
			
		||||
 | 
			
		||||
		tmp0.Subtract(&x3, &z3)
 | 
			
		||||
		tmp1.Subtract(&x2, &z2)
 | 
			
		||||
		x2.Add(&x2, &z2)
 | 
			
		||||
		z2.Add(&x3, &z3)
 | 
			
		||||
		z3.Multiply(&tmp0, &x2)
 | 
			
		||||
		z2.Multiply(&z2, &tmp1)
 | 
			
		||||
		tmp0.Square(&tmp1)
 | 
			
		||||
		tmp1.Square(&x2)
 | 
			
		||||
		x3.Add(&z3, &z2)
 | 
			
		||||
		z2.Subtract(&z3, &z2)
 | 
			
		||||
		x2.Multiply(&tmp1, &tmp0)
 | 
			
		||||
		tmp1.Subtract(&tmp1, &tmp0)
 | 
			
		||||
		z2.Square(&z2)
 | 
			
		||||
 | 
			
		||||
		z3.Mult32(&tmp1, 121666)
 | 
			
		||||
		x3.Square(&x3)
 | 
			
		||||
		tmp0.Add(&tmp0, &z3)
 | 
			
		||||
		z3.Multiply(&x1, &z2)
 | 
			
		||||
		z2.Multiply(&tmp1, &tmp0)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	x2.Swap(&x3, swap)
 | 
			
		||||
	z2.Swap(&z3, swap)
 | 
			
		||||
 | 
			
		||||
	z2.Invert(&z2)
 | 
			
		||||
	x2.Multiply(&x2, &z2)
 | 
			
		||||
	copy(dst[:], x2.Bytes())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ScalarBaseMult sets dst to the product scalar * base where base is the
 | 
			
		||||
// standard generator.
 | 
			
		||||
//
 | 
			
		||||
// It is recommended to use the X25519 function with Basepoint instead, as
 | 
			
		||||
// copying into fixed size arrays can lead to unexpected bugs.
 | 
			
		||||
func ScalarBaseMult(dst, scalar *[32]byte) {
 | 
			
		||||
	ScalarMult(dst, scalar, &basePoint)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// ScalarSize is the size of the scalar input to X25519.
 | 
			
		||||
	ScalarSize = 32
 | 
			
		||||
	// PointSize is the size of the point input to X25519.
 | 
			
		||||
	PointSize = 32
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Basepoint is the canonical Curve25519 generator.
 | 
			
		||||
var Basepoint []byte
 | 
			
		||||
 | 
			
		||||
var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 | 
			
		||||
 | 
			
		||||
func init() { Basepoint = basePoint[:] }
 | 
			
		||||
 | 
			
		||||
func checkBasepoint() {
 | 
			
		||||
	if subtle.ConstantTimeCompare(Basepoint, []byte{
 | 
			
		||||
		0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | 
			
		||||
	}) != 1 {
 | 
			
		||||
		panic("curve25519: global Basepoint value was modified")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// X25519 returns the result of the scalar multiplication (scalar * point),
 | 
			
		||||
// according to RFC 7748, Section 5. scalar, point and the return value are
 | 
			
		||||
// slices of 32 bytes.
 | 
			
		||||
//
 | 
			
		||||
// scalar can be generated at random, for example with crypto/rand. point should
 | 
			
		||||
// be either Basepoint or the output of another X25519 call.
 | 
			
		||||
//
 | 
			
		||||
// If point is Basepoint (but not if it's a different slice with the same
 | 
			
		||||
// contents) a precomputed implementation might be used for performance.
 | 
			
		||||
func X25519(scalar, point []byte) ([]byte, error) {
 | 
			
		||||
	// Outline the body of function, to let the allocation be inlined in the
 | 
			
		||||
	// caller, and possibly avoid escaping to the heap.
 | 
			
		||||
	var dst [32]byte
 | 
			
		||||
	return x25519(&dst, scalar, point)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func x25519(dst *[32]byte, scalar, point []byte) ([]byte, error) {
 | 
			
		||||
	var in [32]byte
 | 
			
		||||
	if l := len(scalar); l != 32 {
 | 
			
		||||
		return nil, fmt.Errorf("bad scalar length: %d, expected %d", l, 32)
 | 
			
		||||
	}
 | 
			
		||||
	if l := len(point); l != 32 {
 | 
			
		||||
		return nil, fmt.Errorf("bad point length: %d, expected %d", l, 32)
 | 
			
		||||
	}
 | 
			
		||||
	copy(in[:], scalar)
 | 
			
		||||
	if &point[0] == &Basepoint[0] {
 | 
			
		||||
		checkBasepoint()
 | 
			
		||||
		ScalarBaseMult(dst, &in)
 | 
			
		||||
	} else {
 | 
			
		||||
		var base, zero [32]byte
 | 
			
		||||
		copy(base[:], point)
 | 
			
		||||
		ScalarMult(dst, &in, &base)
 | 
			
		||||
		if subtle.ConstantTimeCompare(dst[:], zero[:]) == 1 {
 | 
			
		||||
			return nil, fmt.Errorf("bad input point: low order point")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return dst[:], nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										416
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										416
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,416 @@
 | 
			
		||||
// Copyright (c) 2017 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package field implements fast arithmetic modulo 2^255-19.
 | 
			
		||||
package field
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/subtle"
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"math/bits"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Element represents an element of the field GF(2^255-19). Note that this
 | 
			
		||||
// is not a cryptographically secure group, and should only be used to interact
 | 
			
		||||
// with edwards25519.Point coordinates.
 | 
			
		||||
//
 | 
			
		||||
// This type works similarly to math/big.Int, and all arguments and receivers
 | 
			
		||||
// are allowed to alias.
 | 
			
		||||
//
 | 
			
		||||
// The zero value is a valid zero element.
 | 
			
		||||
type Element struct {
 | 
			
		||||
	// An element t represents the integer
 | 
			
		||||
	//     t.l0 + t.l1*2^51 + t.l2*2^102 + t.l3*2^153 + t.l4*2^204
 | 
			
		||||
	//
 | 
			
		||||
	// Between operations, all limbs are expected to be lower than 2^52.
 | 
			
		||||
	l0 uint64
 | 
			
		||||
	l1 uint64
 | 
			
		||||
	l2 uint64
 | 
			
		||||
	l3 uint64
 | 
			
		||||
	l4 uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const maskLow51Bits uint64 = (1 << 51) - 1
 | 
			
		||||
 | 
			
		||||
var feZero = &Element{0, 0, 0, 0, 0}
 | 
			
		||||
 | 
			
		||||
// Zero sets v = 0, and returns v.
 | 
			
		||||
func (v *Element) Zero() *Element {
 | 
			
		||||
	*v = *feZero
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var feOne = &Element{1, 0, 0, 0, 0}
 | 
			
		||||
 | 
			
		||||
// One sets v = 1, and returns v.
 | 
			
		||||
func (v *Element) One() *Element {
 | 
			
		||||
	*v = *feOne
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// reduce reduces v modulo 2^255 - 19 and returns it.
 | 
			
		||||
func (v *Element) reduce() *Element {
 | 
			
		||||
	v.carryPropagate()
 | 
			
		||||
 | 
			
		||||
	// After the light reduction we now have a field element representation
 | 
			
		||||
	// v < 2^255 + 2^13 * 19, but need v < 2^255 - 19.
 | 
			
		||||
 | 
			
		||||
	// If v >= 2^255 - 19, then v + 19 >= 2^255, which would overflow 2^255 - 1,
 | 
			
		||||
	// generating a carry. That is, c will be 0 if v < 2^255 - 19, and 1 otherwise.
 | 
			
		||||
	c := (v.l0 + 19) >> 51
 | 
			
		||||
	c = (v.l1 + c) >> 51
 | 
			
		||||
	c = (v.l2 + c) >> 51
 | 
			
		||||
	c = (v.l3 + c) >> 51
 | 
			
		||||
	c = (v.l4 + c) >> 51
 | 
			
		||||
 | 
			
		||||
	// If v < 2^255 - 19 and c = 0, this will be a no-op. Otherwise, it's
 | 
			
		||||
	// effectively applying the reduction identity to the carry.
 | 
			
		||||
	v.l0 += 19 * c
 | 
			
		||||
 | 
			
		||||
	v.l1 += v.l0 >> 51
 | 
			
		||||
	v.l0 = v.l0 & maskLow51Bits
 | 
			
		||||
	v.l2 += v.l1 >> 51
 | 
			
		||||
	v.l1 = v.l1 & maskLow51Bits
 | 
			
		||||
	v.l3 += v.l2 >> 51
 | 
			
		||||
	v.l2 = v.l2 & maskLow51Bits
 | 
			
		||||
	v.l4 += v.l3 >> 51
 | 
			
		||||
	v.l3 = v.l3 & maskLow51Bits
 | 
			
		||||
	// no additional carry
 | 
			
		||||
	v.l4 = v.l4 & maskLow51Bits
 | 
			
		||||
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Add sets v = a + b, and returns v.
 | 
			
		||||
func (v *Element) Add(a, b *Element) *Element {
 | 
			
		||||
	v.l0 = a.l0 + b.l0
 | 
			
		||||
	v.l1 = a.l1 + b.l1
 | 
			
		||||
	v.l2 = a.l2 + b.l2
 | 
			
		||||
	v.l3 = a.l3 + b.l3
 | 
			
		||||
	v.l4 = a.l4 + b.l4
 | 
			
		||||
	// Using the generic implementation here is actually faster than the
 | 
			
		||||
	// assembly. Probably because the body of this function is so simple that
 | 
			
		||||
	// the compiler can figure out better optimizations by inlining the carry
 | 
			
		||||
	// propagation. TODO
 | 
			
		||||
	return v.carryPropagateGeneric()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Subtract sets v = a - b, and returns v.
 | 
			
		||||
func (v *Element) Subtract(a, b *Element) *Element {
 | 
			
		||||
	// We first add 2 * p, to guarantee the subtraction won't underflow, and
 | 
			
		||||
	// then subtract b (which can be up to 2^255 + 2^13 * 19).
 | 
			
		||||
	v.l0 = (a.l0 + 0xFFFFFFFFFFFDA) - b.l0
 | 
			
		||||
	v.l1 = (a.l1 + 0xFFFFFFFFFFFFE) - b.l1
 | 
			
		||||
	v.l2 = (a.l2 + 0xFFFFFFFFFFFFE) - b.l2
 | 
			
		||||
	v.l3 = (a.l3 + 0xFFFFFFFFFFFFE) - b.l3
 | 
			
		||||
	v.l4 = (a.l4 + 0xFFFFFFFFFFFFE) - b.l4
 | 
			
		||||
	return v.carryPropagate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Negate sets v = -a, and returns v.
 | 
			
		||||
func (v *Element) Negate(a *Element) *Element {
 | 
			
		||||
	return v.Subtract(feZero, a)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invert sets v = 1/z mod p, and returns v.
 | 
			
		||||
//
 | 
			
		||||
// If z == 0, Invert returns v = 0.
 | 
			
		||||
func (v *Element) Invert(z *Element) *Element {
 | 
			
		||||
	// Inversion is implemented as exponentiation with exponent p − 2. It uses the
 | 
			
		||||
	// same sequence of 255 squarings and 11 multiplications as [Curve25519].
 | 
			
		||||
	var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element
 | 
			
		||||
 | 
			
		||||
	z2.Square(z)             // 2
 | 
			
		||||
	t.Square(&z2)            // 4
 | 
			
		||||
	t.Square(&t)             // 8
 | 
			
		||||
	z9.Multiply(&t, z)       // 9
 | 
			
		||||
	z11.Multiply(&z9, &z2)   // 11
 | 
			
		||||
	t.Square(&z11)           // 22
 | 
			
		||||
	z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0
 | 
			
		||||
 | 
			
		||||
	t.Square(&z2_5_0) // 2^6 - 2^1
 | 
			
		||||
	for i := 0; i < 4; i++ {
 | 
			
		||||
		t.Square(&t) // 2^10 - 2^5
 | 
			
		||||
	}
 | 
			
		||||
	z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0
 | 
			
		||||
 | 
			
		||||
	t.Square(&z2_10_0) // 2^11 - 2^1
 | 
			
		||||
	for i := 0; i < 9; i++ {
 | 
			
		||||
		t.Square(&t) // 2^20 - 2^10
 | 
			
		||||
	}
 | 
			
		||||
	z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0
 | 
			
		||||
 | 
			
		||||
	t.Square(&z2_20_0) // 2^21 - 2^1
 | 
			
		||||
	for i := 0; i < 19; i++ {
 | 
			
		||||
		t.Square(&t) // 2^40 - 2^20
 | 
			
		||||
	}
 | 
			
		||||
	t.Multiply(&t, &z2_20_0) // 2^40 - 2^0
 | 
			
		||||
 | 
			
		||||
	t.Square(&t) // 2^41 - 2^1
 | 
			
		||||
	for i := 0; i < 9; i++ {
 | 
			
		||||
		t.Square(&t) // 2^50 - 2^10
 | 
			
		||||
	}
 | 
			
		||||
	z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0
 | 
			
		||||
 | 
			
		||||
	t.Square(&z2_50_0) // 2^51 - 2^1
 | 
			
		||||
	for i := 0; i < 49; i++ {
 | 
			
		||||
		t.Square(&t) // 2^100 - 2^50
 | 
			
		||||
	}
 | 
			
		||||
	z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0
 | 
			
		||||
 | 
			
		||||
	t.Square(&z2_100_0) // 2^101 - 2^1
 | 
			
		||||
	for i := 0; i < 99; i++ {
 | 
			
		||||
		t.Square(&t) // 2^200 - 2^100
 | 
			
		||||
	}
 | 
			
		||||
	t.Multiply(&t, &z2_100_0) // 2^200 - 2^0
 | 
			
		||||
 | 
			
		||||
	t.Square(&t) // 2^201 - 2^1
 | 
			
		||||
	for i := 0; i < 49; i++ {
 | 
			
		||||
		t.Square(&t) // 2^250 - 2^50
 | 
			
		||||
	}
 | 
			
		||||
	t.Multiply(&t, &z2_50_0) // 2^250 - 2^0
 | 
			
		||||
 | 
			
		||||
	t.Square(&t) // 2^251 - 2^1
 | 
			
		||||
	t.Square(&t) // 2^252 - 2^2
 | 
			
		||||
	t.Square(&t) // 2^253 - 2^3
 | 
			
		||||
	t.Square(&t) // 2^254 - 2^4
 | 
			
		||||
	t.Square(&t) // 2^255 - 2^5
 | 
			
		||||
 | 
			
		||||
	return v.Multiply(&t, &z11) // 2^255 - 21
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set sets v = a, and returns v.
 | 
			
		||||
func (v *Element) Set(a *Element) *Element {
 | 
			
		||||
	*v = *a
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetBytes sets v to x, which must be a 32-byte little-endian encoding.
 | 
			
		||||
//
 | 
			
		||||
// Consistent with RFC 7748, the most significant bit (the high bit of the
 | 
			
		||||
// last byte) is ignored, and non-canonical values (2^255-19 through 2^255-1)
 | 
			
		||||
// are accepted. Note that this is laxer than specified by RFC 8032.
 | 
			
		||||
func (v *Element) SetBytes(x []byte) *Element {
 | 
			
		||||
	if len(x) != 32 {
 | 
			
		||||
		panic("edwards25519: invalid field element input size")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Bits 0:51 (bytes 0:8, bits 0:64, shift 0, mask 51).
 | 
			
		||||
	v.l0 = binary.LittleEndian.Uint64(x[0:8])
 | 
			
		||||
	v.l0 &= maskLow51Bits
 | 
			
		||||
	// Bits 51:102 (bytes 6:14, bits 48:112, shift 3, mask 51).
 | 
			
		||||
	v.l1 = binary.LittleEndian.Uint64(x[6:14]) >> 3
 | 
			
		||||
	v.l1 &= maskLow51Bits
 | 
			
		||||
	// Bits 102:153 (bytes 12:20, bits 96:160, shift 6, mask 51).
 | 
			
		||||
	v.l2 = binary.LittleEndian.Uint64(x[12:20]) >> 6
 | 
			
		||||
	v.l2 &= maskLow51Bits
 | 
			
		||||
	// Bits 153:204 (bytes 19:27, bits 152:216, shift 1, mask 51).
 | 
			
		||||
	v.l3 = binary.LittleEndian.Uint64(x[19:27]) >> 1
 | 
			
		||||
	v.l3 &= maskLow51Bits
 | 
			
		||||
	// Bits 204:251 (bytes 24:32, bits 192:256, shift 12, mask 51).
 | 
			
		||||
	// Note: not bytes 25:33, shift 4, to avoid overread.
 | 
			
		||||
	v.l4 = binary.LittleEndian.Uint64(x[24:32]) >> 12
 | 
			
		||||
	v.l4 &= maskLow51Bits
 | 
			
		||||
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bytes returns the canonical 32-byte little-endian encoding of v.
 | 
			
		||||
func (v *Element) Bytes() []byte {
 | 
			
		||||
	// This function is outlined to make the allocations inline in the caller
 | 
			
		||||
	// rather than happen on the heap.
 | 
			
		||||
	var out [32]byte
 | 
			
		||||
	return v.bytes(&out)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (v *Element) bytes(out *[32]byte) []byte {
 | 
			
		||||
	t := *v
 | 
			
		||||
	t.reduce()
 | 
			
		||||
 | 
			
		||||
	var buf [8]byte
 | 
			
		||||
	for i, l := range [5]uint64{t.l0, t.l1, t.l2, t.l3, t.l4} {
 | 
			
		||||
		bitsOffset := i * 51
 | 
			
		||||
		binary.LittleEndian.PutUint64(buf[:], l<<uint(bitsOffset%8))
 | 
			
		||||
		for i, bb := range buf {
 | 
			
		||||
			off := bitsOffset/8 + i
 | 
			
		||||
			if off >= len(out) {
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			out[off] |= bb
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return out[:]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Equal returns 1 if v and u are equal, and 0 otherwise.
 | 
			
		||||
func (v *Element) Equal(u *Element) int {
 | 
			
		||||
	sa, sv := u.Bytes(), v.Bytes()
 | 
			
		||||
	return subtle.ConstantTimeCompare(sa, sv)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mask64Bits returns 0xffffffff if cond is 1, and 0 otherwise.
 | 
			
		||||
func mask64Bits(cond int) uint64 { return ^(uint64(cond) - 1) }
 | 
			
		||||
 | 
			
		||||
// Select sets v to a if cond == 1, and to b if cond == 0.
 | 
			
		||||
func (v *Element) Select(a, b *Element, cond int) *Element {
 | 
			
		||||
	m := mask64Bits(cond)
 | 
			
		||||
	v.l0 = (m & a.l0) | (^m & b.l0)
 | 
			
		||||
	v.l1 = (m & a.l1) | (^m & b.l1)
 | 
			
		||||
	v.l2 = (m & a.l2) | (^m & b.l2)
 | 
			
		||||
	v.l3 = (m & a.l3) | (^m & b.l3)
 | 
			
		||||
	v.l4 = (m & a.l4) | (^m & b.l4)
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Swap swaps v and u if cond == 1 or leaves them unchanged if cond == 0, and returns v.
 | 
			
		||||
func (v *Element) Swap(u *Element, cond int) {
 | 
			
		||||
	m := mask64Bits(cond)
 | 
			
		||||
	t := m & (v.l0 ^ u.l0)
 | 
			
		||||
	v.l0 ^= t
 | 
			
		||||
	u.l0 ^= t
 | 
			
		||||
	t = m & (v.l1 ^ u.l1)
 | 
			
		||||
	v.l1 ^= t
 | 
			
		||||
	u.l1 ^= t
 | 
			
		||||
	t = m & (v.l2 ^ u.l2)
 | 
			
		||||
	v.l2 ^= t
 | 
			
		||||
	u.l2 ^= t
 | 
			
		||||
	t = m & (v.l3 ^ u.l3)
 | 
			
		||||
	v.l3 ^= t
 | 
			
		||||
	u.l3 ^= t
 | 
			
		||||
	t = m & (v.l4 ^ u.l4)
 | 
			
		||||
	v.l4 ^= t
 | 
			
		||||
	u.l4 ^= t
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsNegative returns 1 if v is negative, and 0 otherwise.
 | 
			
		||||
func (v *Element) IsNegative() int {
 | 
			
		||||
	return int(v.Bytes()[0] & 1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Absolute sets v to |u|, and returns v.
 | 
			
		||||
func (v *Element) Absolute(u *Element) *Element {
 | 
			
		||||
	return v.Select(new(Element).Negate(u), u, u.IsNegative())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Multiply sets v = x * y, and returns v.
 | 
			
		||||
func (v *Element) Multiply(x, y *Element) *Element {
 | 
			
		||||
	feMul(v, x, y)
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Square sets v = x * x, and returns v.
 | 
			
		||||
func (v *Element) Square(x *Element) *Element {
 | 
			
		||||
	feSquare(v, x)
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Mult32 sets v = x * y, and returns v.
 | 
			
		||||
func (v *Element) Mult32(x *Element, y uint32) *Element {
 | 
			
		||||
	x0lo, x0hi := mul51(x.l0, y)
 | 
			
		||||
	x1lo, x1hi := mul51(x.l1, y)
 | 
			
		||||
	x2lo, x2hi := mul51(x.l2, y)
 | 
			
		||||
	x3lo, x3hi := mul51(x.l3, y)
 | 
			
		||||
	x4lo, x4hi := mul51(x.l4, y)
 | 
			
		||||
	v.l0 = x0lo + 19*x4hi // carried over per the reduction identity
 | 
			
		||||
	v.l1 = x1lo + x0hi
 | 
			
		||||
	v.l2 = x2lo + x1hi
 | 
			
		||||
	v.l3 = x3lo + x2hi
 | 
			
		||||
	v.l4 = x4lo + x3hi
 | 
			
		||||
	// The hi portions are going to be only 32 bits, plus any previous excess,
 | 
			
		||||
	// so we can skip the carry propagation.
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mul51 returns lo + hi * 2⁵¹ = a * b.
 | 
			
		||||
func mul51(a uint64, b uint32) (lo uint64, hi uint64) {
 | 
			
		||||
	mh, ml := bits.Mul64(a, uint64(b))
 | 
			
		||||
	lo = ml & maskLow51Bits
 | 
			
		||||
	hi = (mh << 13) | (ml >> 51)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pow22523 set v = x^((p-5)/8), and returns v. (p-5)/8 is 2^252-3.
 | 
			
		||||
func (v *Element) Pow22523(x *Element) *Element {
 | 
			
		||||
	var t0, t1, t2 Element
 | 
			
		||||
 | 
			
		||||
	t0.Square(x)             // x^2
 | 
			
		||||
	t1.Square(&t0)           // x^4
 | 
			
		||||
	t1.Square(&t1)           // x^8
 | 
			
		||||
	t1.Multiply(x, &t1)      // x^9
 | 
			
		||||
	t0.Multiply(&t0, &t1)    // x^11
 | 
			
		||||
	t0.Square(&t0)           // x^22
 | 
			
		||||
	t0.Multiply(&t1, &t0)    // x^31
 | 
			
		||||
	t1.Square(&t0)           // x^62
 | 
			
		||||
	for i := 1; i < 5; i++ { // x^992
 | 
			
		||||
		t1.Square(&t1)
 | 
			
		||||
	}
 | 
			
		||||
	t0.Multiply(&t1, &t0)     // x^1023 -> 1023 = 2^10 - 1
 | 
			
		||||
	t1.Square(&t0)            // 2^11 - 2
 | 
			
		||||
	for i := 1; i < 10; i++ { // 2^20 - 2^10
 | 
			
		||||
		t1.Square(&t1)
 | 
			
		||||
	}
 | 
			
		||||
	t1.Multiply(&t1, &t0)     // 2^20 - 1
 | 
			
		||||
	t2.Square(&t1)            // 2^21 - 2
 | 
			
		||||
	for i := 1; i < 20; i++ { // 2^40 - 2^20
 | 
			
		||||
		t2.Square(&t2)
 | 
			
		||||
	}
 | 
			
		||||
	t1.Multiply(&t2, &t1)     // 2^40 - 1
 | 
			
		||||
	t1.Square(&t1)            // 2^41 - 2
 | 
			
		||||
	for i := 1; i < 10; i++ { // 2^50 - 2^10
 | 
			
		||||
		t1.Square(&t1)
 | 
			
		||||
	}
 | 
			
		||||
	t0.Multiply(&t1, &t0)     // 2^50 - 1
 | 
			
		||||
	t1.Square(&t0)            // 2^51 - 2
 | 
			
		||||
	for i := 1; i < 50; i++ { // 2^100 - 2^50
 | 
			
		||||
		t1.Square(&t1)
 | 
			
		||||
	}
 | 
			
		||||
	t1.Multiply(&t1, &t0)      // 2^100 - 1
 | 
			
		||||
	t2.Square(&t1)             // 2^101 - 2
 | 
			
		||||
	for i := 1; i < 100; i++ { // 2^200 - 2^100
 | 
			
		||||
		t2.Square(&t2)
 | 
			
		||||
	}
 | 
			
		||||
	t1.Multiply(&t2, &t1)     // 2^200 - 1
 | 
			
		||||
	t1.Square(&t1)            // 2^201 - 2
 | 
			
		||||
	for i := 1; i < 50; i++ { // 2^250 - 2^50
 | 
			
		||||
		t1.Square(&t1)
 | 
			
		||||
	}
 | 
			
		||||
	t0.Multiply(&t1, &t0)     // 2^250 - 1
 | 
			
		||||
	t0.Square(&t0)            // 2^251 - 2
 | 
			
		||||
	t0.Square(&t0)            // 2^252 - 4
 | 
			
		||||
	return v.Multiply(&t0, x) // 2^252 - 3 -> x^(2^252-3)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// sqrtM1 is 2^((p-1)/4), which squared is equal to -1 by Euler's Criterion.
 | 
			
		||||
var sqrtM1 = &Element{1718705420411056, 234908883556509,
 | 
			
		||||
	2233514472574048, 2117202627021982, 765476049583133}
 | 
			
		||||
 | 
			
		||||
// SqrtRatio sets r to the non-negative square root of the ratio of u and v.
 | 
			
		||||
//
 | 
			
		||||
// If u/v is square, SqrtRatio returns r and 1. If u/v is not square, SqrtRatio
 | 
			
		||||
// sets r according to Section 4.3 of draft-irtf-cfrg-ristretto255-decaf448-00,
 | 
			
		||||
// and returns r and 0.
 | 
			
		||||
func (r *Element) SqrtRatio(u, v *Element) (rr *Element, wasSquare int) {
 | 
			
		||||
	var a, b Element
 | 
			
		||||
 | 
			
		||||
	// r = (u * v3) * (u * v7)^((p-5)/8)
 | 
			
		||||
	v2 := a.Square(v)
 | 
			
		||||
	uv3 := b.Multiply(u, b.Multiply(v2, v))
 | 
			
		||||
	uv7 := a.Multiply(uv3, a.Square(v2))
 | 
			
		||||
	r.Multiply(uv3, r.Pow22523(uv7))
 | 
			
		||||
 | 
			
		||||
	check := a.Multiply(v, a.Square(r)) // check = v * r^2
 | 
			
		||||
 | 
			
		||||
	uNeg := b.Negate(u)
 | 
			
		||||
	correctSignSqrt := check.Equal(u)
 | 
			
		||||
	flippedSignSqrt := check.Equal(uNeg)
 | 
			
		||||
	flippedSignSqrtI := check.Equal(uNeg.Multiply(uNeg, sqrtM1))
 | 
			
		||||
 | 
			
		||||
	rPrime := b.Multiply(r, sqrtM1) // r_prime = SQRT_M1 * r
 | 
			
		||||
	// r = CT_SELECT(r_prime IF flipped_sign_sqrt | flipped_sign_sqrt_i ELSE r)
 | 
			
		||||
	r.Select(rPrime, r, flippedSignSqrt|flippedSignSqrtI)
 | 
			
		||||
 | 
			
		||||
	r.Absolute(r) // Choose the nonnegative square root.
 | 
			
		||||
	return r, correctSignSqrt | flippedSignSqrt
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
// Code generated by command: go run fe_amd64_asm.go -out ../fe_amd64.s -stubs ../fe_amd64.go -pkg field. DO NOT EDIT.
 | 
			
		||||
 | 
			
		||||
// +build amd64,gc,!purego
 | 
			
		||||
 | 
			
		||||
package field
 | 
			
		||||
 | 
			
		||||
// feMul sets out = a * b. It works like feMulGeneric.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func feMul(out *Element, a *Element, b *Element)
 | 
			
		||||
 | 
			
		||||
// feSquare sets out = a * a. It works like feSquareGeneric.
 | 
			
		||||
//go:noescape
 | 
			
		||||
func feSquare(out *Element, a *Element)
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_amd64_noasm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
// Copyright (c) 2019 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build !amd64 || !gc || purego
 | 
			
		||||
// +build !amd64 !gc purego
 | 
			
		||||
 | 
			
		||||
package field
 | 
			
		||||
 | 
			
		||||
func feMul(v, x, y *Element) { feMulGeneric(v, x, y) }
 | 
			
		||||
 | 
			
		||||
func feSquare(v, x *Element) { feSquareGeneric(v, x) }
 | 
			
		||||
							
								
								
									
										16
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
			
		||||
// Copyright (c) 2020 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build arm64 && gc && !purego
 | 
			
		||||
// +build arm64,gc,!purego
 | 
			
		||||
 | 
			
		||||
package field
 | 
			
		||||
 | 
			
		||||
//go:noescape
 | 
			
		||||
func carryPropagate(v *Element)
 | 
			
		||||
 | 
			
		||||
func (v *Element) carryPropagate() *Element {
 | 
			
		||||
	carryPropagate(v)
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_arm64_noasm.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
// Copyright (c) 2021 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build !arm64 || !gc || purego
 | 
			
		||||
// +build !arm64 !gc purego
 | 
			
		||||
 | 
			
		||||
package field
 | 
			
		||||
 | 
			
		||||
func (v *Element) carryPropagate() *Element {
 | 
			
		||||
	return v.carryPropagateGeneric()
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										264
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								vendor/golang.org/x/crypto/curve25519/internal/field/fe_generic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,264 @@
 | 
			
		||||
// Copyright (c) 2017 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
package field
 | 
			
		||||
 | 
			
		||||
import "math/bits"
 | 
			
		||||
 | 
			
		||||
// uint128 holds a 128-bit number as two 64-bit limbs, for use with the
 | 
			
		||||
// bits.Mul64 and bits.Add64 intrinsics.
 | 
			
		||||
type uint128 struct {
 | 
			
		||||
	lo, hi uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// mul64 returns a * b.
 | 
			
		||||
func mul64(a, b uint64) uint128 {
 | 
			
		||||
	hi, lo := bits.Mul64(a, b)
 | 
			
		||||
	return uint128{lo, hi}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// addMul64 returns v + a * b.
 | 
			
		||||
func addMul64(v uint128, a, b uint64) uint128 {
 | 
			
		||||
	hi, lo := bits.Mul64(a, b)
 | 
			
		||||
	lo, c := bits.Add64(lo, v.lo, 0)
 | 
			
		||||
	hi, _ = bits.Add64(hi, v.hi, c)
 | 
			
		||||
	return uint128{lo, hi}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// shiftRightBy51 returns a >> 51. a is assumed to be at most 115 bits.
 | 
			
		||||
func shiftRightBy51(a uint128) uint64 {
 | 
			
		||||
	return (a.hi << (64 - 51)) | (a.lo >> 51)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func feMulGeneric(v, a, b *Element) {
 | 
			
		||||
	a0 := a.l0
 | 
			
		||||
	a1 := a.l1
 | 
			
		||||
	a2 := a.l2
 | 
			
		||||
	a3 := a.l3
 | 
			
		||||
	a4 := a.l4
 | 
			
		||||
 | 
			
		||||
	b0 := b.l0
 | 
			
		||||
	b1 := b.l1
 | 
			
		||||
	b2 := b.l2
 | 
			
		||||
	b3 := b.l3
 | 
			
		||||
	b4 := b.l4
 | 
			
		||||
 | 
			
		||||
	// Limb multiplication works like pen-and-paper columnar multiplication, but
 | 
			
		||||
	// with 51-bit limbs instead of digits.
 | 
			
		||||
	//
 | 
			
		||||
	//                          a4   a3   a2   a1   a0  x
 | 
			
		||||
	//                          b4   b3   b2   b1   b0  =
 | 
			
		||||
	//                         ------------------------
 | 
			
		||||
	//                        a4b0 a3b0 a2b0 a1b0 a0b0  +
 | 
			
		||||
	//                   a4b1 a3b1 a2b1 a1b1 a0b1       +
 | 
			
		||||
	//              a4b2 a3b2 a2b2 a1b2 a0b2            +
 | 
			
		||||
	//         a4b3 a3b3 a2b3 a1b3 a0b3                 +
 | 
			
		||||
	//    a4b4 a3b4 a2b4 a1b4 a0b4                      =
 | 
			
		||||
	//   ----------------------------------------------
 | 
			
		||||
	//      r8   r7   r6   r5   r4   r3   r2   r1   r0
 | 
			
		||||
	//
 | 
			
		||||
	// We can then use the reduction identity (a * 2²⁵⁵ + b = a * 19 + b) to
 | 
			
		||||
	// reduce the limbs that would overflow 255 bits. r5 * 2²⁵⁵ becomes 19 * r5,
 | 
			
		||||
	// r6 * 2³⁰⁶ becomes 19 * r6 * 2⁵¹, etc.
 | 
			
		||||
	//
 | 
			
		||||
	// Reduction can be carried out simultaneously to multiplication. For
 | 
			
		||||
	// example, we do not compute r5: whenever the result of a multiplication
 | 
			
		||||
	// belongs to r5, like a1b4, we multiply it by 19 and add the result to r0.
 | 
			
		||||
	//
 | 
			
		||||
	//            a4b0    a3b0    a2b0    a1b0    a0b0  +
 | 
			
		||||
	//            a3b1    a2b1    a1b1    a0b1 19×a4b1  +
 | 
			
		||||
	//            a2b2    a1b2    a0b2 19×a4b2 19×a3b2  +
 | 
			
		||||
	//            a1b3    a0b3 19×a4b3 19×a3b3 19×a2b3  +
 | 
			
		||||
	//            a0b4 19×a4b4 19×a3b4 19×a2b4 19×a1b4  =
 | 
			
		||||
	//           --------------------------------------
 | 
			
		||||
	//              r4      r3      r2      r1      r0
 | 
			
		||||
	//
 | 
			
		||||
	// Finally we add up the columns into wide, overlapping limbs.
 | 
			
		||||
 | 
			
		||||
	a1_19 := a1 * 19
 | 
			
		||||
	a2_19 := a2 * 19
 | 
			
		||||
	a3_19 := a3 * 19
 | 
			
		||||
	a4_19 := a4 * 19
 | 
			
		||||
 | 
			
		||||
	// r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
 | 
			
		||||
	r0 := mul64(a0, b0)
 | 
			
		||||
	r0 = addMul64(r0, a1_19, b4)
 | 
			
		||||
	r0 = addMul64(r0, a2_19, b3)
 | 
			
		||||
	r0 = addMul64(r0, a3_19, b2)
 | 
			
		||||
	r0 = addMul64(r0, a4_19, b1)
 | 
			
		||||
 | 
			
		||||
	// r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2)
 | 
			
		||||
	r1 := mul64(a0, b1)
 | 
			
		||||
	r1 = addMul64(r1, a1, b0)
 | 
			
		||||
	r1 = addMul64(r1, a2_19, b4)
 | 
			
		||||
	r1 = addMul64(r1, a3_19, b3)
 | 
			
		||||
	r1 = addMul64(r1, a4_19, b2)
 | 
			
		||||
 | 
			
		||||
	// r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3)
 | 
			
		||||
	r2 := mul64(a0, b2)
 | 
			
		||||
	r2 = addMul64(r2, a1, b1)
 | 
			
		||||
	r2 = addMul64(r2, a2, b0)
 | 
			
		||||
	r2 = addMul64(r2, a3_19, b4)
 | 
			
		||||
	r2 = addMul64(r2, a4_19, b3)
 | 
			
		||||
 | 
			
		||||
	// r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4
 | 
			
		||||
	r3 := mul64(a0, b3)
 | 
			
		||||
	r3 = addMul64(r3, a1, b2)
 | 
			
		||||
	r3 = addMul64(r3, a2, b1)
 | 
			
		||||
	r3 = addMul64(r3, a3, b0)
 | 
			
		||||
	r3 = addMul64(r3, a4_19, b4)
 | 
			
		||||
 | 
			
		||||
	// r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
 | 
			
		||||
	r4 := mul64(a0, b4)
 | 
			
		||||
	r4 = addMul64(r4, a1, b3)
 | 
			
		||||
	r4 = addMul64(r4, a2, b2)
 | 
			
		||||
	r4 = addMul64(r4, a3, b1)
 | 
			
		||||
	r4 = addMul64(r4, a4, b0)
 | 
			
		||||
 | 
			
		||||
	// After the multiplication, we need to reduce (carry) the five coefficients
 | 
			
		||||
	// to obtain a result with limbs that are at most slightly larger than 2⁵¹,
 | 
			
		||||
	// to respect the Element invariant.
 | 
			
		||||
	//
 | 
			
		||||
	// Overall, the reduction works the same as carryPropagate, except with
 | 
			
		||||
	// wider inputs: we take the carry for each coefficient by shifting it right
 | 
			
		||||
	// by 51, and add it to the limb above it. The top carry is multiplied by 19
 | 
			
		||||
	// according to the reduction identity and added to the lowest limb.
 | 
			
		||||
	//
 | 
			
		||||
	// The largest coefficient (r0) will be at most 111 bits, which guarantees
 | 
			
		||||
	// that all carries are at most 111 - 51 = 60 bits, which fits in a uint64.
 | 
			
		||||
	//
 | 
			
		||||
	//     r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1)
 | 
			
		||||
	//     r0 < 2⁵²×2⁵² + 19×(2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵² + 2⁵²×2⁵²)
 | 
			
		||||
	//     r0 < (1 + 19 × 4) × 2⁵² × 2⁵²
 | 
			
		||||
	//     r0 < 2⁷ × 2⁵² × 2⁵²
 | 
			
		||||
	//     r0 < 2¹¹¹
 | 
			
		||||
	//
 | 
			
		||||
	// Moreover, the top coefficient (r4) is at most 107 bits, so c4 is at most
 | 
			
		||||
	// 56 bits, and c4 * 19 is at most 61 bits, which again fits in a uint64 and
 | 
			
		||||
	// allows us to easily apply the reduction identity.
 | 
			
		||||
	//
 | 
			
		||||
	//     r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0
 | 
			
		||||
	//     r4 < 5 × 2⁵² × 2⁵²
 | 
			
		||||
	//     r4 < 2¹⁰⁷
 | 
			
		||||
	//
 | 
			
		||||
 | 
			
		||||
	c0 := shiftRightBy51(r0)
 | 
			
		||||
	c1 := shiftRightBy51(r1)
 | 
			
		||||
	c2 := shiftRightBy51(r2)
 | 
			
		||||
	c3 := shiftRightBy51(r3)
 | 
			
		||||
	c4 := shiftRightBy51(r4)
 | 
			
		||||
 | 
			
		||||
	rr0 := r0.lo&maskLow51Bits + c4*19
 | 
			
		||||
	rr1 := r1.lo&maskLow51Bits + c0
 | 
			
		||||
	rr2 := r2.lo&maskLow51Bits + c1
 | 
			
		||||
	rr3 := r3.lo&maskLow51Bits + c2
 | 
			
		||||
	rr4 := r4.lo&maskLow51Bits + c3
 | 
			
		||||
 | 
			
		||||
	// Now all coefficients fit into 64-bit registers but are still too large to
 | 
			
		||||
	// be passed around as a Element. We therefore do one last carry chain,
 | 
			
		||||
	// where the carries will be small enough to fit in the wiggle room above 2⁵¹.
 | 
			
		||||
	*v = Element{rr0, rr1, rr2, rr3, rr4}
 | 
			
		||||
	v.carryPropagate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func feSquareGeneric(v, a *Element) {
 | 
			
		||||
	l0 := a.l0
 | 
			
		||||
	l1 := a.l1
 | 
			
		||||
	l2 := a.l2
 | 
			
		||||
	l3 := a.l3
 | 
			
		||||
	l4 := a.l4
 | 
			
		||||
 | 
			
		||||
	// Squaring works precisely like multiplication above, but thanks to its
 | 
			
		||||
	// symmetry we get to group a few terms together.
 | 
			
		||||
	//
 | 
			
		||||
	//                          l4   l3   l2   l1   l0  x
 | 
			
		||||
	//                          l4   l3   l2   l1   l0  =
 | 
			
		||||
	//                         ------------------------
 | 
			
		||||
	//                        l4l0 l3l0 l2l0 l1l0 l0l0  +
 | 
			
		||||
	//                   l4l1 l3l1 l2l1 l1l1 l0l1       +
 | 
			
		||||
	//              l4l2 l3l2 l2l2 l1l2 l0l2            +
 | 
			
		||||
	//         l4l3 l3l3 l2l3 l1l3 l0l3                 +
 | 
			
		||||
	//    l4l4 l3l4 l2l4 l1l4 l0l4                      =
 | 
			
		||||
	//   ----------------------------------------------
 | 
			
		||||
	//      r8   r7   r6   r5   r4   r3   r2   r1   r0
 | 
			
		||||
	//
 | 
			
		||||
	//            l4l0    l3l0    l2l0    l1l0    l0l0  +
 | 
			
		||||
	//            l3l1    l2l1    l1l1    l0l1 19×l4l1  +
 | 
			
		||||
	//            l2l2    l1l2    l0l2 19×l4l2 19×l3l2  +
 | 
			
		||||
	//            l1l3    l0l3 19×l4l3 19×l3l3 19×l2l3  +
 | 
			
		||||
	//            l0l4 19×l4l4 19×l3l4 19×l2l4 19×l1l4  =
 | 
			
		||||
	//           --------------------------------------
 | 
			
		||||
	//              r4      r3      r2      r1      r0
 | 
			
		||||
	//
 | 
			
		||||
	// With precomputed 2×, 19×, and 2×19× terms, we can compute each limb with
 | 
			
		||||
	// only three Mul64 and four Add64, instead of five and eight.
 | 
			
		||||
 | 
			
		||||
	l0_2 := l0 * 2
 | 
			
		||||
	l1_2 := l1 * 2
 | 
			
		||||
 | 
			
		||||
	l1_38 := l1 * 38
 | 
			
		||||
	l2_38 := l2 * 38
 | 
			
		||||
	l3_38 := l3 * 38
 | 
			
		||||
 | 
			
		||||
	l3_19 := l3 * 19
 | 
			
		||||
	l4_19 := l4 * 19
 | 
			
		||||
 | 
			
		||||
	// r0 = l0×l0 + 19×(l1×l4 + l2×l3 + l3×l2 + l4×l1) = l0×l0 + 19×2×(l1×l4 + l2×l3)
 | 
			
		||||
	r0 := mul64(l0, l0)
 | 
			
		||||
	r0 = addMul64(r0, l1_38, l4)
 | 
			
		||||
	r0 = addMul64(r0, l2_38, l3)
 | 
			
		||||
 | 
			
		||||
	// r1 = l0×l1 + l1×l0 + 19×(l2×l4 + l3×l3 + l4×l2) = 2×l0×l1 + 19×2×l2×l4 + 19×l3×l3
 | 
			
		||||
	r1 := mul64(l0_2, l1)
 | 
			
		||||
	r1 = addMul64(r1, l2_38, l4)
 | 
			
		||||
	r1 = addMul64(r1, l3_19, l3)
 | 
			
		||||
 | 
			
		||||
	// r2 = l0×l2 + l1×l1 + l2×l0 + 19×(l3×l4 + l4×l3) = 2×l0×l2 + l1×l1 + 19×2×l3×l4
 | 
			
		||||
	r2 := mul64(l0_2, l2)
 | 
			
		||||
	r2 = addMul64(r2, l1, l1)
 | 
			
		||||
	r2 = addMul64(r2, l3_38, l4)
 | 
			
		||||
 | 
			
		||||
	// r3 = l0×l3 + l1×l2 + l2×l1 + l3×l0 + 19×l4×l4 = 2×l0×l3 + 2×l1×l2 + 19×l4×l4
 | 
			
		||||
	r3 := mul64(l0_2, l3)
 | 
			
		||||
	r3 = addMul64(r3, l1_2, l2)
 | 
			
		||||
	r3 = addMul64(r3, l4_19, l4)
 | 
			
		||||
 | 
			
		||||
	// r4 = l0×l4 + l1×l3 + l2×l2 + l3×l1 + l4×l0 = 2×l0×l4 + 2×l1×l3 + l2×l2
 | 
			
		||||
	r4 := mul64(l0_2, l4)
 | 
			
		||||
	r4 = addMul64(r4, l1_2, l3)
 | 
			
		||||
	r4 = addMul64(r4, l2, l2)
 | 
			
		||||
 | 
			
		||||
	c0 := shiftRightBy51(r0)
 | 
			
		||||
	c1 := shiftRightBy51(r1)
 | 
			
		||||
	c2 := shiftRightBy51(r2)
 | 
			
		||||
	c3 := shiftRightBy51(r3)
 | 
			
		||||
	c4 := shiftRightBy51(r4)
 | 
			
		||||
 | 
			
		||||
	rr0 := r0.lo&maskLow51Bits + c4*19
 | 
			
		||||
	rr1 := r1.lo&maskLow51Bits + c0
 | 
			
		||||
	rr2 := r2.lo&maskLow51Bits + c1
 | 
			
		||||
	rr3 := r3.lo&maskLow51Bits + c2
 | 
			
		||||
	rr4 := r4.lo&maskLow51Bits + c3
 | 
			
		||||
 | 
			
		||||
	*v = Element{rr0, rr1, rr2, rr3, rr4}
 | 
			
		||||
	v.carryPropagate()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// carryPropagate brings the limbs below 52 bits by applying the reduction
 | 
			
		||||
// identity (a * 2²⁵⁵ + b = a * 19 + b) to the l4 carry. TODO inline
 | 
			
		||||
func (v *Element) carryPropagateGeneric() *Element {
 | 
			
		||||
	c0 := v.l0 >> 51
 | 
			
		||||
	c1 := v.l1 >> 51
 | 
			
		||||
	c2 := v.l2 >> 51
 | 
			
		||||
	c3 := v.l3 >> 51
 | 
			
		||||
	c4 := v.l4 >> 51
 | 
			
		||||
 | 
			
		||||
	v.l0 = v.l0&maskLow51Bits + c4*19
 | 
			
		||||
	v.l1 = v.l1&maskLow51Bits + c0
 | 
			
		||||
	v.l2 = v.l2&maskLow51Bits + c1
 | 
			
		||||
	v.l3 = v.l3&maskLow51Bits + c2
 | 
			
		||||
	v.l4 = v.l4&maskLow51Bits + c3
 | 
			
		||||
 | 
			
		||||
	return v
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								vendor/golang.org/x/crypto/ed25519/ed25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								vendor/golang.org/x/crypto/ed25519/ed25519.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
// Copyright 2019 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
// Package ed25519 implements the Ed25519 signature algorithm. See
 | 
			
		||||
// https://ed25519.cr.yp.to/.
 | 
			
		||||
//
 | 
			
		||||
// These functions are also compatible with the “Ed25519” function defined in
 | 
			
		||||
// RFC 8032. However, unlike RFC 8032's formulation, this package's private key
 | 
			
		||||
// representation includes a public key suffix to make multiple signing
 | 
			
		||||
// operations with the same key more efficient. This package refers to the RFC
 | 
			
		||||
// 8032 private key as the “seed”.
 | 
			
		||||
//
 | 
			
		||||
// Beginning with Go 1.13, the functionality of this package was moved to the
 | 
			
		||||
// standard library as crypto/ed25519. This package only acts as a compatibility
 | 
			
		||||
// wrapper.
 | 
			
		||||
package ed25519
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/ed25519"
 | 
			
		||||
	"io"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// PublicKeySize is the size, in bytes, of public keys as used in this package.
 | 
			
		||||
	PublicKeySize = 32
 | 
			
		||||
	// PrivateKeySize is the size, in bytes, of private keys as used in this package.
 | 
			
		||||
	PrivateKeySize = 64
 | 
			
		||||
	// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
 | 
			
		||||
	SignatureSize = 64
 | 
			
		||||
	// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
 | 
			
		||||
	SeedSize = 32
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// PublicKey is the type of Ed25519 public keys.
 | 
			
		||||
//
 | 
			
		||||
// This type is an alias for crypto/ed25519's PublicKey type.
 | 
			
		||||
// See the crypto/ed25519 package for the methods on this type.
 | 
			
		||||
type PublicKey = ed25519.PublicKey
 | 
			
		||||
 | 
			
		||||
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
 | 
			
		||||
//
 | 
			
		||||
// This type is an alias for crypto/ed25519's PrivateKey type.
 | 
			
		||||
// See the crypto/ed25519 package for the methods on this type.
 | 
			
		||||
type PrivateKey = ed25519.PrivateKey
 | 
			
		||||
 | 
			
		||||
// GenerateKey generates a public/private key pair using entropy from rand.
 | 
			
		||||
// If rand is nil, crypto/rand.Reader will be used.
 | 
			
		||||
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
 | 
			
		||||
	return ed25519.GenerateKey(rand)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewKeyFromSeed calculates a private key from a seed. It will panic if
 | 
			
		||||
// len(seed) is not SeedSize. This function is provided for interoperability
 | 
			
		||||
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
 | 
			
		||||
// package.
 | 
			
		||||
func NewKeyFromSeed(seed []byte) PrivateKey {
 | 
			
		||||
	return ed25519.NewKeyFromSeed(seed)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Sign signs the message with privateKey and returns a signature. It will
 | 
			
		||||
// panic if len(privateKey) is not PrivateKeySize.
 | 
			
		||||
func Sign(privateKey PrivateKey, message []byte) []byte {
 | 
			
		||||
	return ed25519.Sign(privateKey, message)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Verify reports whether sig is a valid signature of message by publicKey. It
 | 
			
		||||
// will panic if len(publicKey) is not PublicKeySize.
 | 
			
		||||
func Verify(publicKey PublicKey, message, sig []byte) bool {
 | 
			
		||||
	return ed25519.Verify(publicKey, message, sig)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								vendor/golang.org/x/crypto/internal/poly1305/bits_compat.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
			
		||||
// Copyright 2019 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build !go1.13
 | 
			
		||||
// +build !go1.13
 | 
			
		||||
 | 
			
		||||
package poly1305
 | 
			
		||||
 | 
			
		||||
// Generic fallbacks for the math/bits intrinsics, copied from
 | 
			
		||||
// src/math/bits/bits.go. They were added in Go 1.12, but Add64 and Sum64 had
 | 
			
		||||
// variable time fallbacks until Go 1.13.
 | 
			
		||||
 | 
			
		||||
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
 | 
			
		||||
	sum = x + y + carry
 | 
			
		||||
	carryOut = ((x & y) | ((x | y) &^ sum)) >> 63
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
 | 
			
		||||
	diff = x - y - borrow
 | 
			
		||||
	borrowOut = ((^x & y) | (^(x ^ y) & diff)) >> 63
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bitsMul64(x, y uint64) (hi, lo uint64) {
 | 
			
		||||
	const mask32 = 1<<32 - 1
 | 
			
		||||
	x0 := x & mask32
 | 
			
		||||
	x1 := x >> 32
 | 
			
		||||
	y0 := y & mask32
 | 
			
		||||
	y1 := y >> 32
 | 
			
		||||
	w0 := x0 * y0
 | 
			
		||||
	t := x1*y0 + w0>>32
 | 
			
		||||
	w1 := t & mask32
 | 
			
		||||
	w2 := t >> 32
 | 
			
		||||
	w1 += x0 * y1
 | 
			
		||||
	hi = x1*y1 + w2 + w1>>32
 | 
			
		||||
	lo = x * y
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/golang.org/x/crypto/internal/poly1305/bits_go1.13.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
// Copyright 2019 The Go Authors. All rights reserved.
 | 
			
		||||
// Use of this source code is governed by a BSD-style
 | 
			
		||||
// license that can be found in the LICENSE file.
 | 
			
		||||
 | 
			
		||||
//go:build go1.13
 | 
			
		||||
// +build go1.13
 | 
			
		||||
 | 
			
		||||
package poly1305
 | 
			
		||||
 | 
			
		||||
import "math/bits"
 | 
			
		||||
 | 
			
		||||
func bitsAdd64(x, y, carry uint64) (sum, carryOut uint64) {
 | 
			
		||||
	return bits.Add64(x, y, carry)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bitsSub64(x, y, borrow uint64) (diff, borrowOut uint64) {
 | 
			
		||||
	return bits.Sub64(x, y, borrow)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bitsMul64(x, y uint64) (hi, lo uint64) {
 | 
			
		||||
	return bits.Mul64(x, y)
 | 
			
		||||
}
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user