226 lines
5.8 KiB
Go
226 lines
5.8 KiB
Go
package main
|
|
|
|
import (
|
|
utils "anytunnel/at-common"
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/astaxie/beego"
|
|
)
|
|
|
|
func userIsNoTraffic(userID string) bool {
|
|
now := time.Now().Unix()
|
|
rs, err := db.Query(db.AR().Select("user_id").From("package").Where(map[string]interface{}{
|
|
"user_id": userID,
|
|
"start_time <": now,
|
|
"end_time >": now,
|
|
"bytes_left >": 0,
|
|
}).Limit(1))
|
|
if err != nil {
|
|
log.Printf("query user package ERR:%s", err)
|
|
return false
|
|
}
|
|
return rs.Len() == 0
|
|
}
|
|
func killUser(userID string, forbidden bool, reason string) {
|
|
//log.Printf("kill user : %s", userID)
|
|
//1.kill all user's online server
|
|
rs, err := db.Query(db.AR().Select("cs_id,cluster_id").From("online").Where(map[string]interface{}{
|
|
"user_id": userID,
|
|
"cs_type": "server",
|
|
}))
|
|
if err != nil {
|
|
return
|
|
}
|
|
allOnlineServerIDs := rs.Rows()
|
|
for _, online := range allOnlineServerIDs {
|
|
killCS(online["cluster_id"], online["cs_id"], true)
|
|
}
|
|
//2.kill all user's online client
|
|
rs, err = db.Query(db.AR().Select("cs_id,cluster_id").From("online").Where(map[string]interface{}{
|
|
"user_id": userID,
|
|
"cs_type": "client",
|
|
}))
|
|
if err != nil {
|
|
return
|
|
}
|
|
allOnlineClientIDs := rs.Rows()
|
|
for _, online := range allOnlineClientIDs {
|
|
killCS(online["cluster_id"], online["cs_id"], false)
|
|
}
|
|
//3.kill all user's online tunnel
|
|
killUserTunnel(userID)
|
|
//4.if user forbidden or not
|
|
if forbidden {
|
|
_, err := db.Exec(db.AR().Update("user", map[string]interface{}{"is_forbidden": 1, "forbidden_reason": reason}, map[string]interface{}{"user_id": userID}))
|
|
if err != nil {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func killCS(clusterID, csID string, isServer bool) (err error) {
|
|
typ := "server"
|
|
if !isServer {
|
|
typ = "client"
|
|
}
|
|
log.Printf("kill %s : %s", typ, csID)
|
|
rs, err := db.Query(db.AR().From("cluster").Where(map[string]interface{}{"is_delete": 0}))
|
|
if err != nil {
|
|
return
|
|
}
|
|
if rs.Len() == 0 {
|
|
err = fmt.Errorf("empty cluster for cluster_id:%s", clusterID)
|
|
return
|
|
}
|
|
cluster := rs.Row()
|
|
|
|
rs, err = db.Query(db.AR().From(typ).Where(map[string]interface{}{
|
|
typ + "_id": csID,
|
|
"is_delete": 0,
|
|
}))
|
|
if err != nil {
|
|
return
|
|
}
|
|
if rs.Len() == 0 {
|
|
err = fmt.Errorf("empty %s for %s_id:%s", typ, typ, csID)
|
|
return
|
|
}
|
|
item := rs.Row()
|
|
url := fmt.Sprintf("https://%s:%s/%s/offline/%s", cluster["ip"], beego.AppConfig.String("cluster.api.port"), typ, item["token"])
|
|
body, code, err := utils.HttpGet(url)
|
|
if err != nil {
|
|
log.Printf("kill server fail,code: %d,body: %s ,ERR: %s ", code, string(body), err)
|
|
}
|
|
return
|
|
}
|
|
func killUserTunnel(userID string) {
|
|
|
|
rs, err := db.Query(db.AR().From("conn").Where(map[string]interface{}{"user_id": userID}))
|
|
if err != nil {
|
|
return
|
|
}
|
|
if rs.Len() == 0 {
|
|
//err = fmt.Errorf("killUserTunnel , empty tunnel for user_id:%s", userID)
|
|
return
|
|
}
|
|
for _, conn := range rs.Rows() {
|
|
log.Printf("kill tunnel:%s , userID: %s", conn["tunnel_id"], userID)
|
|
rs, err = db.Query(db.AR().From("cluster").Where(map[string]interface{}{
|
|
"cluster_id": conn["cluster_id"],
|
|
"is_delete": 0,
|
|
}))
|
|
if err != nil {
|
|
return
|
|
}
|
|
if rs.Len() == 0 {
|
|
//err = fmt.Errorf("killUserTunnel , empty cluster for cluster_id:%s", conn["cluster_id"])
|
|
return
|
|
}
|
|
cluster := rs.Row()
|
|
url := fmt.Sprintf("https://%s:%s/port/close/%s", cluster["ip"], beego.AppConfig.String("cluster.api.port"), conn["tunnel_id"])
|
|
body, code, err := utils.HttpGet(url)
|
|
if err != nil {
|
|
log.Printf("kill tunnel fail,code: %d,body: %s ,ERR: %s ", code, string(body), err)
|
|
return
|
|
}
|
|
}
|
|
db.Exec(db.AR().Delete("conn", map[string]interface{}{
|
|
"user_id": userID,
|
|
}))
|
|
}
|
|
|
|
func csIsOnline(csID, csType string) bool {
|
|
rs, err := db.Query(db.AR().From("online").Where(map[string]interface{}{
|
|
"cs_id": csID,
|
|
"cs_type": csType,
|
|
}))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return rs.Len() == 1
|
|
}
|
|
func killTunnel(tunnelID, clusterID string) (err error) {
|
|
rs, err := db.Query(db.AR().From("cluster").Where(map[string]interface{}{
|
|
"cluster_id": clusterID,
|
|
"is_delete": 0,
|
|
}))
|
|
if err != nil {
|
|
log.Printf("kill tunnel fail,ERR:%s", err)
|
|
return
|
|
}
|
|
if rs.Len() == 0 {
|
|
return
|
|
}
|
|
cluster := rs.Row()
|
|
url := fmt.Sprintf("https://%s:%s/port/close/%s", cluster["ip"], beego.AppConfig.String("cluster.api.port"), tunnelID)
|
|
body, code, err := utils.HttpGet(url)
|
|
if err != nil {
|
|
log.Printf("kill tunnel fail,code: %d,body: %s ,ERR: %s ", code, string(body), err)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
func GetCS(csID, csType string) (row map[string]string, err error) {
|
|
rs, err := db.Query(db.AR().From(csType).Where(map[string]interface{}{
|
|
csType + "_id": csID,
|
|
"is_delete": 0,
|
|
}))
|
|
if err != nil {
|
|
log.Printf("query %s fail,ERR:%s", csType, err)
|
|
return
|
|
}
|
|
if rs.Len() == 0 {
|
|
err = fmt.Errorf("%s not exists", csType)
|
|
return
|
|
}
|
|
row = rs.Row()
|
|
return
|
|
}
|
|
func GetCluster(clusterID string) (row map[string]string, err error) {
|
|
rs, err := db.Query(db.AR().From("cluster").Where(map[string]interface{}{
|
|
"cluster_id": clusterID,
|
|
"is_delete": 0,
|
|
}))
|
|
if err != nil {
|
|
log.Printf("query clusterfail,ERR:%s", err)
|
|
return
|
|
}
|
|
if rs.Len() == 0 {
|
|
err = fmt.Errorf("cluster not exists ,clusterID:%s", clusterID)
|
|
return
|
|
}
|
|
row = rs.Row()
|
|
return
|
|
}
|
|
func csIsOnCluster(clusterID, csID, csType string) (exists bool) {
|
|
cluster, err := GetCluster(clusterID)
|
|
if err != nil {
|
|
return
|
|
}
|
|
cs, err := GetCS(csID, csType)
|
|
if err != nil {
|
|
return
|
|
}
|
|
url := fmt.Sprintf("https://%s:%s/%s/status/%s", cluster["ip"], beego.AppConfig.String("cluster.api.port"), csType, cs["token"])
|
|
body, code, err := utils.HttpGet(url)
|
|
if err != nil {
|
|
|
|
log.Printf("get %s status fail,code: %d,body: %s ,ERR: %s ", csType, code, string(body), err)
|
|
return
|
|
}
|
|
res := map[string]interface{}{}
|
|
err = json.Unmarshal(body, &res)
|
|
if err != nil {
|
|
log.Printf("parse csIsOnCluster result ERR:%s,body:%s", err, string(body))
|
|
}
|
|
respCode, err := strconv.ParseUint(fmt.Sprintf("%.0f", res["code"]), 10, 64)
|
|
if err != nil {
|
|
return
|
|
}
|
|
return respCode == 1
|
|
}
|