init
This commit is contained in:
@@ -0,0 +1,622 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
utils "anytunnel/at-common"
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
CSSTATUS_TYPE_SERVER = "server"
|
||||
CSSTATUS_TYPE_CLIENT = "client"
|
||||
CSSTATUS_ACTION_ONLINE = "online"
|
||||
CSSTATUS_ACTION_OFFLINE = "offline"
|
||||
)
|
||||
|
||||
type CSStatus struct {
|
||||
url string
|
||||
bufchn chan CSStatusAction
|
||||
}
|
||||
type CSStatusAction struct {
|
||||
Type string
|
||||
Token string
|
||||
Action string
|
||||
IP string
|
||||
}
|
||||
|
||||
func NewCSStatus() *CSStatus {
|
||||
s := CSStatus{
|
||||
url: cfg.GetString("url.status"),
|
||||
bufchn: make(chan CSStatusAction, 500),
|
||||
}
|
||||
s.init()
|
||||
return &s
|
||||
}
|
||||
func (cs *CSStatus) init() {
|
||||
go func() {
|
||||
for {
|
||||
action := <-cs.bufchn
|
||||
var tryCount = 0
|
||||
for tryCount <= cfg.GetInt("url.fail-retry") {
|
||||
tryCount++
|
||||
_url := utils.UrlArgs(cs.url, fmt.Sprintf("type=%s&token=%s&action=%s&ip=%s", action.Type, action.Token, action.Action, action.IP))
|
||||
body, code, err := HttpGet(_url)
|
||||
if err == nil && code == cfg.GetInt("url.success-code") {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Warnf("report online/offline status fail to url %s, err: %s", cs.url, err)
|
||||
} else {
|
||||
err = fmt.Errorf("token error")
|
||||
log.Warnf("report online/offline status fail to url %s, code: %d, except: %d ,body:%s", cs.url, code, cfg.GetInt("url.success-code"), string(body))
|
||||
}
|
||||
if err != nil && tryCount <= cfg.GetInt("url.fail-retry") {
|
||||
time.Sleep(time.Second * time.Duration(cfg.GetInt("url.fail-wait")))
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
func (cs *CSStatus) ClientOnline(token string, addr net.Addr) {
|
||||
cs.pushStatus(CSSTATUS_TYPE_CLIENT, token, CSSTATUS_ACTION_ONLINE, addr)
|
||||
}
|
||||
func (cs *CSStatus) ClientOffline(token string, addr net.Addr) {
|
||||
cs.pushStatus(CSSTATUS_TYPE_CLIENT, token, CSSTATUS_ACTION_OFFLINE, addr)
|
||||
}
|
||||
func (cs *CSStatus) ServerOnline(token string, addr net.Addr) {
|
||||
cs.pushStatus(CSSTATUS_TYPE_SERVER, token, CSSTATUS_ACTION_ONLINE, addr)
|
||||
}
|
||||
func (cs *CSStatus) ServerOffline(token string, addr net.Addr) {
|
||||
cs.pushStatus(CSSTATUS_TYPE_SERVER, token, CSSTATUS_ACTION_OFFLINE, addr)
|
||||
}
|
||||
func (cs *CSStatus) pushStatus(typ, token, action string, addr net.Addr) {
|
||||
if cs.url == "" {
|
||||
return
|
||||
}
|
||||
_addr := addr.String()
|
||||
ip := _addr[0:strings.Index(_addr, ":")]
|
||||
cs.bufchn <- CSStatusAction{
|
||||
Action: action,
|
||||
Type: typ,
|
||||
Token: token,
|
||||
IP: ip,
|
||||
}
|
||||
}
|
||||
|
||||
//###################ConnMap######################
|
||||
type ConnMap struct {
|
||||
data utils.ConcurrentMap
|
||||
}
|
||||
type ConnItem struct {
|
||||
ServerToken string
|
||||
TunnelID uint64
|
||||
Count uint64
|
||||
}
|
||||
type ConnTimeout struct {
|
||||
Conn *net.Conn
|
||||
ServerToken string
|
||||
TunnelID uint64
|
||||
LastTime int64
|
||||
}
|
||||
|
||||
func NewConnMap() *ConnMap {
|
||||
cm := ConnMap{
|
||||
data: utils.NewConcurrentMap(),
|
||||
}
|
||||
cm.gc()
|
||||
return &cm
|
||||
}
|
||||
func (m *ConnMap) IntToString(id uint64) string {
|
||||
return strconv.FormatUint(id, 10)
|
||||
}
|
||||
func (m *ConnMap) Get(id uint64) (conn *net.Conn, exists bool) {
|
||||
mid := m.IntToString(id)
|
||||
_conn, exists := m.data.Get(mid)
|
||||
if exists {
|
||||
conn = (_conn).(ConnTimeout).Conn
|
||||
}
|
||||
return
|
||||
}
|
||||
func (m *ConnMap) Put(serverToken string, tunnleID, connid uint64, conn *net.Conn) {
|
||||
mid := m.IntToString(connid)
|
||||
m.data.Set(mid, ConnTimeout{
|
||||
Conn: conn,
|
||||
LastTime: time.Now().Unix(),
|
||||
ServerToken: serverToken,
|
||||
TunnelID: tunnleID,
|
||||
})
|
||||
//b, _ := m.data.MarshalJSON()
|
||||
//fmt.Println("put:", serverToken, tunnleID, connid, m.GetTunnelConnCountMap(), string(b))
|
||||
return
|
||||
}
|
||||
|
||||
func (m *ConnMap) Delete(id uint64) {
|
||||
mid := m.IntToString(id)
|
||||
_conn, exists := m.data.Get(mid)
|
||||
if exists {
|
||||
(*(_conn).(ConnTimeout).Conn).Close()
|
||||
}
|
||||
m.data.Remove(mid)
|
||||
}
|
||||
func (m *ConnMap) ClearTimeout(id uint64) {
|
||||
mid := m.IntToString(id)
|
||||
_conn, exists := m.data.Get(mid)
|
||||
if exists {
|
||||
_c := _conn.(ConnTimeout)
|
||||
_c.LastTime = 0
|
||||
m.data.Set(mid, _c)
|
||||
}
|
||||
}
|
||||
func (m *ConnMap) GetTunnelConnCountMap() map[uint64]ConnItem {
|
||||
countMap := map[uint64]ConnItem{}
|
||||
for _, k := range m.data.Keys() {
|
||||
v, _ := m.data.Get(k)
|
||||
c := v.(ConnTimeout)
|
||||
item, ok := countMap[c.TunnelID]
|
||||
if !ok {
|
||||
countMap[c.TunnelID] = ConnItem{
|
||||
Count: 1,
|
||||
ServerToken: c.ServerToken,
|
||||
TunnelID: c.TunnelID,
|
||||
}
|
||||
} else {
|
||||
item.Count = item.Count + 1
|
||||
countMap[c.TunnelID] = item
|
||||
}
|
||||
}
|
||||
return countMap
|
||||
}
|
||||
func (m *ConnMap) gc() {
|
||||
go func() {
|
||||
for {
|
||||
for _, k := range m.data.Keys() {
|
||||
v, _ := m.data.Get(k)
|
||||
c := v.(ConnTimeout)
|
||||
if c.LastTime > 0 && time.Now().Unix()-c.LastTime > SERVER_CONN_IDLE_SECONDS {
|
||||
(*c.Conn).Close()
|
||||
m.data.Remove(k)
|
||||
}
|
||||
}
|
||||
time.Sleep(60 * time.Second)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
//###############ClusterTunnelPool##################
|
||||
type ClusterTunnel struct {
|
||||
TunnelID uint64
|
||||
ServerToken string
|
||||
ServerBindIP string
|
||||
ServerListenPort int
|
||||
ClientToken string
|
||||
ClientLocalHost string
|
||||
ClientLocalPort int
|
||||
Protocol int
|
||||
BytesPerSec float64
|
||||
}
|
||||
type ClusterTunnelPool struct {
|
||||
pool utils.ConcurrentMap
|
||||
}
|
||||
|
||||
func NewClusterTunnelPool() ClusterTunnelPool {
|
||||
return ClusterTunnelPool{
|
||||
pool: utils.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
func (m *ClusterTunnelPool) IntToString(id uint64) string {
|
||||
return strconv.FormatUint(id, 10)
|
||||
}
|
||||
func (t *ClusterTunnelPool) Set(tunnel ClusterTunnel) {
|
||||
mid := t.IntToString(tunnel.TunnelID)
|
||||
t.pool.Set(mid, tunnel)
|
||||
}
|
||||
func (t *ClusterTunnelPool) Get(tunnelID uint64) (tunnel ClusterTunnel, err error) {
|
||||
mid := t.IntToString(tunnelID)
|
||||
v, e := t.pool.Get(mid)
|
||||
if !e {
|
||||
err = fmt.Errorf("tunnel %d not exists", tunnelID)
|
||||
return
|
||||
}
|
||||
return v.(ClusterTunnel), err
|
||||
}
|
||||
func (t *ClusterTunnelPool) Exists(tunnelID uint64) bool {
|
||||
mid := t.IntToString(tunnelID)
|
||||
return t.pool.Has(mid)
|
||||
}
|
||||
func (t *ClusterTunnelPool) Delete(tunnelID uint64) {
|
||||
mid := t.IntToString(tunnelID)
|
||||
t.pool.Remove(mid)
|
||||
}
|
||||
|
||||
//###############ClusterServerControlChannelPool##################
|
||||
type ClusterServerControlChannel struct {
|
||||
ServerToken string
|
||||
ServerMessageChannel *utils.MessageChannel
|
||||
}
|
||||
type ClusterServerControlChannelPool struct {
|
||||
pool utils.ConcurrentMap
|
||||
}
|
||||
|
||||
func NewClusterServerControlChannelPool() ClusterServerControlChannelPool {
|
||||
return ClusterServerControlChannelPool{
|
||||
pool: utils.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
func (t *ClusterServerControlChannelPool) Set(serverChannel ClusterServerControlChannel) {
|
||||
t.pool.Set(serverChannel.ServerToken, serverChannel)
|
||||
}
|
||||
func (t *ClusterServerControlChannelPool) Get(serverToken string) (serverChannel ClusterServerControlChannel, err error) {
|
||||
v, e := t.pool.Get(serverToken)
|
||||
if !e {
|
||||
err = fmt.Errorf("ClusterServerControlChannel %s not exists", serverToken)
|
||||
return
|
||||
}
|
||||
return v.(ClusterServerControlChannel), err
|
||||
}
|
||||
func (t *ClusterServerControlChannelPool) Exists(serverToken string) bool {
|
||||
return t.pool.Has(serverToken)
|
||||
}
|
||||
func (t *ClusterServerControlChannelPool) Delete(serverToken string) {
|
||||
v, e := t.pool.Get(serverToken)
|
||||
if e {
|
||||
v.(ClusterServerControlChannel).ServerMessageChannel.CloseConn()
|
||||
}
|
||||
t.pool.Remove(serverToken)
|
||||
}
|
||||
|
||||
//###############ClusterClientControlChannelPool##################
|
||||
type ClusterClientControlChannel struct {
|
||||
ClientToken string
|
||||
ClientMessageChannel *utils.MessageChannel
|
||||
}
|
||||
type ClusterClientControlChannelPool struct {
|
||||
pool utils.ConcurrentMap
|
||||
}
|
||||
|
||||
func NewClusterClientControlChannelPool() ClusterClientControlChannelPool {
|
||||
return ClusterClientControlChannelPool{
|
||||
pool: utils.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
func (t *ClusterClientControlChannelPool) Set(clientChannel ClusterClientControlChannel) {
|
||||
t.pool.Set(clientChannel.ClientToken, clientChannel)
|
||||
}
|
||||
func (t *ClusterClientControlChannelPool) Get(clientToken string) (clientChannel ClusterClientControlChannel, err error) {
|
||||
v, e := t.pool.Get(clientToken)
|
||||
if !e {
|
||||
err = fmt.Errorf("ClusterClientControlChannel %s not exists", clientToken)
|
||||
return
|
||||
}
|
||||
return v.(ClusterClientControlChannel), err
|
||||
}
|
||||
func (t *ClusterClientControlChannelPool) Exists(clientToken string) bool {
|
||||
return t.pool.Has(clientToken)
|
||||
}
|
||||
func (t *ClusterClientControlChannelPool) Delete(clientToken string) {
|
||||
v, e := t.pool.Get(clientToken)
|
||||
if e {
|
||||
v.(ClusterClientControlChannel).ClientMessageChannel.CloseConn()
|
||||
}
|
||||
t.pool.Remove(clientToken)
|
||||
}
|
||||
|
||||
//
|
||||
//###############counter##################
|
||||
type TunnelTrafficCounter struct {
|
||||
counter utils.ConcurrentMap
|
||||
bufchn chan TunnelTrafficEntry
|
||||
}
|
||||
type TunnelTrafficEntry struct {
|
||||
IsPositive bool
|
||||
TunnelID uint64
|
||||
CountBytes uint64
|
||||
}
|
||||
|
||||
//map[string]uint64{}
|
||||
func NewTunnelTrafficCounter() TunnelTrafficCounter {
|
||||
tc := TunnelTrafficCounter{
|
||||
counter: utils.NewConcurrentMap(),
|
||||
bufchn: make(chan TunnelTrafficEntry, 500000),
|
||||
}
|
||||
tc.init()
|
||||
return tc
|
||||
}
|
||||
func (m *TunnelTrafficCounter) IntToString(id uint64) string {
|
||||
return strconv.FormatUint(id, 10)
|
||||
}
|
||||
func (tc *TunnelTrafficCounter) init() {
|
||||
go func() {
|
||||
for {
|
||||
entry := <-tc.bufchn
|
||||
mid := tc.IntToString(entry.TunnelID)
|
||||
tc.counter.Upsert(mid, nil, func(exists bool, vold interface{}, vnew interface{}) (res interface{}) {
|
||||
if vold != nil {
|
||||
if entry.IsPositive {
|
||||
vold.(map[string]uint64)["positive"] = vold.(map[string]uint64)["positive"] + entry.CountBytes
|
||||
} else {
|
||||
vold.(map[string]uint64)["negative"] = vold.(map[string]uint64)["negative"] + entry.CountBytes
|
||||
}
|
||||
res = vold
|
||||
}
|
||||
return
|
||||
})
|
||||
}
|
||||
}()
|
||||
}
|
||||
func (tc *TunnelTrafficCounter) InitTunnel(tunnelID uint64) {
|
||||
mid := tc.IntToString(tunnelID)
|
||||
tc.counter.Set(mid, map[string]uint64{
|
||||
"positive": 0,
|
||||
"negative": 0,
|
||||
})
|
||||
}
|
||||
func (tc *TunnelTrafficCounter) DeleteTunnel(tunnelID uint64) {
|
||||
mid := tc.IntToString(tunnelID)
|
||||
tc.counter.Remove(mid)
|
||||
}
|
||||
func (tc *TunnelTrafficCounter) AddPositive(tunnelID, bytesCount uint64) {
|
||||
tc.bufchn <- TunnelTrafficEntry{
|
||||
TunnelID: tunnelID,
|
||||
IsPositive: true,
|
||||
CountBytes: bytesCount,
|
||||
}
|
||||
}
|
||||
func (tc *TunnelTrafficCounter) AddNegative(tunnelID, bytesCount uint64) {
|
||||
tc.bufchn <- TunnelTrafficEntry{
|
||||
TunnelID: tunnelID,
|
||||
IsPositive: false,
|
||||
CountBytes: bytesCount,
|
||||
}
|
||||
}
|
||||
func (tc *TunnelTrafficCounter) AllDataJSON() ([]byte, error) {
|
||||
JSON := utils.TrafficStatistics{
|
||||
Total: utils.TrafficTotal{
|
||||
Tunnels: poolTunnel.pool.Count(),
|
||||
Servers: poolServerControlChannel.pool.Count(),
|
||||
Clients: poolClientControlChannel.pool.Count(),
|
||||
UploadBytes: 0,
|
||||
DownloadBytes: 0,
|
||||
TotalBytes: 0,
|
||||
Connections: serverConns.data.Count(),
|
||||
},
|
||||
}
|
||||
tunnelCount := serverConns.GetTunnelConnCountMap()
|
||||
|
||||
data := map[string]map[string]uint64{}
|
||||
for nk, nv := range tc.counter.Items() {
|
||||
tid, _ := strconv.ParseUint(nk, 10, 64)
|
||||
var count uint64
|
||||
if v, ok := tunnelCount[tid]; ok {
|
||||
count = v.Count
|
||||
}
|
||||
uploadBytes := nv.(map[string]uint64)["positive"]
|
||||
downloadBytes := nv.(map[string]uint64)["negative"]
|
||||
|
||||
tunnel, _ := poolTunnel.Get(tid)
|
||||
data[nk] = map[string]uint64{
|
||||
"positive": uploadBytes,
|
||||
"negative": downloadBytes,
|
||||
"limit": uint64(tunnel.BytesPerSec),
|
||||
"connections": count,
|
||||
}
|
||||
JSON.Total.UploadBytes += uploadBytes
|
||||
JSON.Total.DownloadBytes += downloadBytes
|
||||
}
|
||||
JSON.Total.TotalBytes = JSON.Total.UploadBytes + JSON.Total.DownloadBytes
|
||||
JSON.Traffic = data
|
||||
return json.Marshal(JSON)
|
||||
}
|
||||
func (tc *TunnelTrafficCounter) TunnelDataJSON(tunnelID uint64) ([]byte, error) {
|
||||
mid := tc.IntToString(tunnelID)
|
||||
if v, e := tc.counter.Get(mid); e {
|
||||
return json.Marshal(v)
|
||||
}
|
||||
return []byte("{}"), nil
|
||||
}
|
||||
func (tc *TunnelTrafficCounter) AllData() map[string]map[string]uint64 {
|
||||
data := map[string]map[string]uint64{}
|
||||
tc.counter.IterCb(func(nk string, nv interface{}) {
|
||||
if nv != nil {
|
||||
data[nk] = map[string]uint64{
|
||||
"positive": nv.(map[string]uint64)["positive"],
|
||||
"negative": nv.(map[string]uint64)["negative"],
|
||||
}
|
||||
}
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
//###############ServerTunnelPool##################
|
||||
type ServerTunnelPool struct {
|
||||
pool utils.ConcurrentMap
|
||||
}
|
||||
|
||||
func NewServerTunnelPool() ServerTunnelPool {
|
||||
return ServerTunnelPool{
|
||||
pool: utils.NewConcurrentMap(),
|
||||
}
|
||||
}
|
||||
func (s *ServerTunnelPool) AddTunnel(ServerToken string, TunnelID uint64) {
|
||||
v, ok := s.pool.Get(ServerToken)
|
||||
if !ok {
|
||||
v = map[uint64]bool{}
|
||||
}
|
||||
_v := v.(map[uint64]bool)
|
||||
_v[TunnelID] = true
|
||||
s.pool.Set(ServerToken, _v)
|
||||
}
|
||||
func (s *ServerTunnelPool) DeleteServer(ServerToken string) {
|
||||
if v, ok := s.pool.Get(ServerToken); ok {
|
||||
_v := v.(map[uint64]bool)
|
||||
for TunnelID := range _v {
|
||||
poolTunnel.Delete(TunnelID)
|
||||
trafficCounter.DeleteTunnel(TunnelID)
|
||||
}
|
||||
s.pool.Remove(ServerToken)
|
||||
}
|
||||
}
|
||||
|
||||
//###############ServerTunnelPool##################
|
||||
|
||||
type PortData struct {
|
||||
}
|
||||
|
||||
func NewPortData() PortData {
|
||||
return PortData{}
|
||||
}
|
||||
func (d *PortData) Rcovery(ServerToken string) (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
log.Warnf("recovery return an error , ERR: %s", err)
|
||||
}
|
||||
}()
|
||||
path, err := d.getPath(ServerToken)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var oldContets []byte
|
||||
oldContets, err = d.fileGetContents(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
oldContetsLines := strings.Split(string(oldContets), "\n")
|
||||
// log.Debugf("maybe %d tunnels to recovery,ServerToken:%s", len(oldContetsLines), ServerToken)
|
||||
for _, line := range oldContetsLines {
|
||||
lineFields := strings.Fields(line)
|
||||
if len(lineFields) != 2 {
|
||||
continue
|
||||
}
|
||||
ip := cfg.GetStringSlice("port.ip-api")[0]
|
||||
if ip == "0.0.0.0" || ip == "" {
|
||||
ip = "127.0.0.1"
|
||||
}
|
||||
url := fmt.Sprintf("https://%s:%d%s", ip, 37080, lineFields[1])
|
||||
utils.HttpGet(url)
|
||||
// _, code, err := utils.HttpGet(url)
|
||||
// if err != nil {
|
||||
// log.Debugf("recovery err : %d %s %s", code, err, url)
|
||||
|
||||
// } else {
|
||||
// log.Debugf("recovery result : %d %s", code, url)
|
||||
// }
|
||||
}
|
||||
return
|
||||
}
|
||||
func (d *PortData) Delete(token string, tunnelID uint64) (err error) {
|
||||
return d._StoreOrDelete(ClusterTunnel{
|
||||
TunnelID: tunnelID,
|
||||
ServerToken: token,
|
||||
}, false)
|
||||
}
|
||||
func (d *PortData) DeleteServer(token string) (err error) {
|
||||
path, err := d.getPath(token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return os.Remove(path)
|
||||
}
|
||||
func (d *PortData) Store(t ClusterTunnel) (err error) {
|
||||
return d._StoreOrDelete(t, true)
|
||||
}
|
||||
func (d *PortData) _StoreOrDelete(t ClusterTunnel, isStore bool) (err error) {
|
||||
// d.l.Lock()
|
||||
// defer d.l.Unlock()
|
||||
path, err := d.getPath(t.ServerToken)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
cmd := ""
|
||||
if isStore {
|
||||
cmd = fmt.Sprintf("/port/open/%d/%s/%s/%d/%s/%s/%d/%d/%.0f", t.TunnelID, t.ServerToken, t.ServerBindIP, t.ServerListenPort,
|
||||
t.ClientToken, t.ClientLocalHost, t.ClientLocalPort, t.Protocol, t.BytesPerSec)
|
||||
}
|
||||
content := fmt.Sprintf("%d %s\n", t.TunnelID, cmd)
|
||||
if d.exists(path) {
|
||||
var oldContets []byte
|
||||
oldContets, err = d.fileGetContents(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
oldContetsLines := strings.Split(string(oldContets), "\n")
|
||||
newContests := []byte{}
|
||||
writer := bytes.NewBuffer(newContests)
|
||||
found := false
|
||||
for _, line := range oldContetsLines {
|
||||
lineFields := strings.Fields(line)
|
||||
if len(lineFields) != 2 {
|
||||
continue
|
||||
}
|
||||
id, _ := strconv.Atoi(lineFields[0])
|
||||
if uint64(id) == t.TunnelID {
|
||||
found = true
|
||||
if isStore {
|
||||
writer.WriteString(content)
|
||||
}
|
||||
continue
|
||||
} else {
|
||||
writer.WriteString(line + "\n")
|
||||
}
|
||||
}
|
||||
if !found && isStore {
|
||||
writer.WriteString(content)
|
||||
}
|
||||
err = d.filePutContents(path, writer.Bytes())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
} else if isStore {
|
||||
err = d.mkdirs(path)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = d.filePutContents(path, []byte(content))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
func (d *PortData) getPath(token string) (path string, err error) {
|
||||
return filepath.Abs(fmt.Sprintf("%s/%d/%s", cfg.GetString("data.dir"), crc32.ChecksumIEEE([]byte(token))%10, token))
|
||||
}
|
||||
func (d *PortData) mkdirs(path string) (err error) {
|
||||
err = os.MkdirAll(filepath.Dir(path), os.ModePerm)
|
||||
return
|
||||
}
|
||||
func (d *PortData) exists(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
return os.IsExist(err)
|
||||
}
|
||||
func (d *PortData) fileGetContents(filename string) ([]byte, error) {
|
||||
fp, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, os.ModePerm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fp.Close()
|
||||
reader := bufio.NewReader(fp)
|
||||
contents, _ := ioutil.ReadAll(reader)
|
||||
return contents, nil
|
||||
}
|
||||
|
||||
func (d *PortData) filePutContents(filename string, content []byte) error {
|
||||
mode := os.O_CREATE | os.O_WRONLY | os.O_TRUNC
|
||||
fp, err := os.OpenFile(filename, mode, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fp.Close()
|
||||
_, err = fp.Write(content)
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user