2023-05-24 15:10:15 +09:00
|
|
|
package azure
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/md5"
|
|
|
|
|
"encoding/hex"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"os"
|
|
|
|
|
"os/exec"
|
|
|
|
|
"path"
|
|
|
|
|
"runtime"
|
|
|
|
|
"sort"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"syscall"
|
|
|
|
|
"time"
|
|
|
|
|
|
2023-06-20 17:02:09 +09:00
|
|
|
"repositories.action2quare.com/ayo/gocommon"
|
2023-05-24 15:10:15 +09:00
|
|
|
"repositories.action2quare.com/ayo/gocommon/logger"
|
|
|
|
|
|
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func SortVersions(versions []string) []string {
|
|
|
|
|
sort.Slice(versions, func(i, j int) bool {
|
|
|
|
|
leftnum := 0
|
|
|
|
|
for _, iv := range strings.Split(versions[i], ".") {
|
|
|
|
|
n, _ := strconv.Atoi(iv)
|
|
|
|
|
leftnum += leftnum<<8 + n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rightnum := 0
|
|
|
|
|
for _, iv := range strings.Split(versions[j], ".") {
|
|
|
|
|
n, _ := strconv.Atoi(iv)
|
|
|
|
|
rightnum += rightnum<<8 + n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return leftnum < rightnum
|
|
|
|
|
})
|
|
|
|
|
return versions
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
HoustonStatPoolCount = int(10)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type HoustonStatReport struct {
|
|
|
|
|
Region string `json:"region"`
|
|
|
|
|
FreeMemory float64 `json:"freeMemory"`
|
|
|
|
|
FreePercent float64 `json:"freePercent"`
|
|
|
|
|
CPUUsage float64 `json:"cpuUsage"`
|
|
|
|
|
PlayingUsers int `json:"users"`
|
|
|
|
|
PlayingSessions int `json:"sessions"`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var ErrUpdateUnnecessary = errors.New("binary is already latest")
|
|
|
|
|
|
|
|
|
|
func SelfUpdateUsingScript(replycache *MessageReplyCache, graph *Graph, patchroot string, force bool) (err error) {
|
|
|
|
|
// 1. 다운로드
|
|
|
|
|
var linkfilearg string
|
|
|
|
|
if replycache != nil {
|
|
|
|
|
if replycache.ReplyWrap == nil {
|
|
|
|
|
hostname, _ := os.Hostname()
|
|
|
|
|
replycache.ReplyWrap = replycache.SourceActivity().MakeWrap().WithPrefix(hostname)
|
|
|
|
|
}
|
|
|
|
|
linkfile := replycache.Serialize()
|
|
|
|
|
linkfilearg = fmt.Sprintf("-updatelink=%s", linkfile)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
currentexe, _ := os.Executable()
|
|
|
|
|
currentexe = strings.ReplaceAll(currentexe, "\\", "/")
|
|
|
|
|
exefile := path.Base(currentexe)
|
|
|
|
|
if runtime.GOOS == "windows" && !strings.HasSuffix(exefile, ".exe") {
|
|
|
|
|
exefile += ".exe"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newbinary := fmt.Sprintf("%s.%s", exefile, time.Now().Format("2006.01.02-15.04.05"))
|
|
|
|
|
downloadurl := path.Join(patchroot, exefile)
|
|
|
|
|
|
|
|
|
|
err = graph.DownloadFile(downloadurl, newbinary)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_, err = os.Stat(newbinary)
|
|
|
|
|
if os.IsNotExist(err) {
|
|
|
|
|
err = errors.New("다운로드 실패 : " + newbinary)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !force {
|
|
|
|
|
currentfile, e := os.Open(currentexe)
|
|
|
|
|
if e != nil {
|
|
|
|
|
return e
|
|
|
|
|
}
|
|
|
|
|
defer currentfile.Close()
|
|
|
|
|
|
|
|
|
|
hash1 := md5.New()
|
|
|
|
|
_, err = io.Copy(hash1, currentfile)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
currentHash := hex.EncodeToString(hash1.Sum(nil))
|
|
|
|
|
|
|
|
|
|
nextfile, e := os.Open(newbinary)
|
|
|
|
|
if e != nil {
|
|
|
|
|
return e
|
|
|
|
|
}
|
|
|
|
|
defer nextfile.Close()
|
|
|
|
|
hash2 := md5.New()
|
|
|
|
|
_, err = io.Copy(hash2, nextfile)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
nextHash := hex.EncodeToString(hash2.Sum(nil))
|
|
|
|
|
|
|
|
|
|
if currentHash == nextHash {
|
|
|
|
|
// 해시가 같으니까 업데이트 할 필요가 없다.
|
|
|
|
|
return ErrUpdateUnnecessary
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var scriptfileName string
|
|
|
|
|
if runtime.GOOS == "linux" {
|
|
|
|
|
scriptfileName = "selfupdate.sh"
|
|
|
|
|
} else if runtime.GOOS == "windows" {
|
|
|
|
|
scriptfileName = "selfupdate.bat"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
scripturl := path.Join(patchroot, scriptfileName)
|
|
|
|
|
if _, err = os.Stat(scriptfileName); os.IsExist(err) {
|
|
|
|
|
err = os.Remove(scriptfileName)
|
|
|
|
|
} else {
|
|
|
|
|
err = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. 스크립트 다운로드
|
|
|
|
|
err = graph.DownloadFile(scripturl, scriptfileName)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var nextArgs []string
|
|
|
|
|
for _, arg := range os.Args[1:] {
|
|
|
|
|
// -updatelink : selfupdate시에
|
|
|
|
|
if !strings.HasPrefix(arg, "-updatelink=") && arg != "-prefetch" {
|
|
|
|
|
nextArgs = append(nextArgs, arg)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pid := strconv.Itoa(os.Getpid())
|
|
|
|
|
args := append([]string{
|
|
|
|
|
pid,
|
|
|
|
|
newbinary,
|
|
|
|
|
exefile,
|
|
|
|
|
}, nextArgs...)
|
|
|
|
|
|
|
|
|
|
if len(linkfilearg) > 0 {
|
|
|
|
|
args = append(args, linkfilearg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 독립 실행
|
|
|
|
|
if runtime.GOOS == "linux" {
|
|
|
|
|
// 실행 가능한 권한 부여
|
|
|
|
|
err = os.Chmod(scriptfileName, 0777)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// 실행
|
|
|
|
|
env := os.Environ()
|
|
|
|
|
currentpath := path.Dir(currentexe)
|
|
|
|
|
argv0 := path.Join(currentpath, scriptfileName)
|
|
|
|
|
args = append([]string{"/bin/bash", argv0}, args...)
|
|
|
|
|
err = syscall.Exec(args[0], args, env)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
} else if runtime.GOOS == "windows" {
|
|
|
|
|
windowsargs := append([]string{
|
|
|
|
|
"/C",
|
|
|
|
|
"start",
|
|
|
|
|
scriptfileName,
|
|
|
|
|
}, args...)
|
|
|
|
|
|
|
|
|
|
cmd := exec.Command("cmd.exe", windowsargs...)
|
|
|
|
|
err = cmd.Run()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ReplyUpdateComplete() {
|
|
|
|
|
defer func() {
|
|
|
|
|
r := recover()
|
|
|
|
|
if r != nil {
|
|
|
|
|
logger.Error(r)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
|
2023-06-20 17:02:09 +09:00
|
|
|
if len(*gocommon.Linkupdate) > 0 {
|
|
|
|
|
cache := DeserializeMessageReplyCache(*gocommon.Linkupdate)
|
2023-05-24 15:10:15 +09:00
|
|
|
if cache != nil {
|
2023-06-20 17:02:09 +09:00
|
|
|
os.Remove(*gocommon.Linkupdate)
|
2023-05-24 15:10:15 +09:00
|
|
|
if cache.ReplyWrap != nil {
|
|
|
|
|
cache.ReplyWrap.Update(cache.Replyaid, "업데이트 완료")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// var objectIDCounter = readRandomUint32()
|
|
|
|
|
// var processUnique = processUniqueBytes()
|
|
|
|
|
|
|
|
|
|
// func processUniqueBytes() [5]byte {
|
|
|
|
|
// var b [5]byte
|
|
|
|
|
// _, err := io.ReadFull(rand.Reader, b[:])
|
|
|
|
|
// if err != nil {
|
|
|
|
|
// panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err))
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return b
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// func readRandomUint32() uint32 {
|
|
|
|
|
// var b [4]byte
|
|
|
|
|
// _, err := io.ReadFull(rand.Reader, b[:])
|
|
|
|
|
// if err != nil {
|
|
|
|
|
// panic(fmt.Errorf("cannot initialize objectid package with crypto.rand.Reader: %v", err))
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return (uint32(b[0]) << 0) | (uint32(b[1]) << 8) | (uint32(b[2]) << 16) | (uint32(b[3]) << 24)
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
type BsonMarshaler[T any] struct {
|
|
|
|
|
val T
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewBsonMarshaler[T any](val T) *BsonMarshaler[T] {
|
|
|
|
|
return &BsonMarshaler[T]{
|
|
|
|
|
val: val,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *BsonMarshaler[T]) MarshalBinary() (data []byte, err error) {
|
|
|
|
|
return bson.Marshal(m.val)
|
|
|
|
|
}
|