Files

188 lines
4.3 KiB
Go

package control
import (
"context"
"encoding/json"
"flag"
"fmt"
"io"
"google.golang.org/grpc"
"github.com/p4gefau1t/trojan-go/api/service"
"github.com/p4gefau1t/trojan-go/common"
"github.com/p4gefau1t/trojan-go/log"
"github.com/p4gefau1t/trojan-go/option"
)
type apiController struct {
address *string
key *string
hash *string
cert *string
cmd *string
password *string
add *bool
delete *bool
modify *bool
list *bool
uploadSpeedLimit *int
downloadSpeedLimit *int
ipLimit *int
ctx context.Context
}
func (apiController) Name() string {
return "api"
}
func (o *apiController) listUsers(apiClient service.TrojanServerServiceClient) error {
stream, err := apiClient.ListUsers(o.ctx, &service.ListUsersRequest{})
if err != nil {
return err
}
defer stream.CloseSend()
result := []*service.ListUsersResponse{}
for {
resp, err := stream.Recv()
if err != nil {
if err == io.EOF {
break
}
return err
}
result = append(result, resp)
}
data, err := json.Marshal(result)
common.Must(err)
fmt.Println(string(data))
return nil
}
func (o *apiController) getUsers(apiClient service.TrojanServerServiceClient) error {
stream, err := apiClient.GetUsers(o.ctx)
if err != nil {
return err
}
defer stream.CloseSend()
err = stream.Send(&service.GetUsersRequest{
User: &service.User{
Password: *o.password,
Hash: *o.hash,
},
})
if err != nil {
return err
}
resp, err := stream.Recv()
if err != nil {
return err
}
data, err := json.Marshal(resp)
common.Must(err)
fmt.Print(string(data))
return nil
}
func (o *apiController) setUsers(apiClient service.TrojanServerServiceClient) error {
stream, err := apiClient.SetUsers(o.ctx)
if err != nil {
return err
}
defer stream.CloseSend()
req := &service.SetUsersRequest{
Status: &service.UserStatus{
User: &service.User{
Password: *o.password,
Hash: *o.hash,
},
IpLimit: int32(*o.ipLimit),
SpeedLimit: &service.Speed{
UploadSpeed: uint64(*o.uploadSpeedLimit),
DownloadSpeed: uint64(*o.downloadSpeedLimit),
},
},
}
switch {
case *o.add:
req.Operation = service.SetUsersRequest_Add
case *o.modify:
req.Operation = service.SetUsersRequest_Modify
case *o.delete:
req.Operation = service.SetUsersRequest_Delete
default:
return common.NewError("Invalid operation")
}
err = stream.Send(req)
if err != nil {
return err
}
resp, err := stream.Recv()
if err != nil {
return err
}
if resp.Success {
fmt.Println("Done")
} else {
fmt.Println("Failed: " + resp.Info)
}
return nil
}
func (o *apiController) Handle() error {
if *o.cmd == "" {
return common.NewError("")
}
conn, err := grpc.Dial(*o.address, grpc.WithInsecure())
if err != nil {
log.Error(err)
return nil
}
defer conn.Close()
apiClient := service.NewTrojanServerServiceClient(conn)
switch *o.cmd {
case "list":
err := o.listUsers(apiClient)
if err != nil {
log.Error(err)
}
case "get":
err := o.getUsers(apiClient)
if err != nil {
log.Error(err)
}
case "set":
err := o.setUsers(apiClient)
if err != nil {
log.Error(err)
}
default:
log.Error("unknown command " + *o.cmd)
}
return nil
}
func (o *apiController) Priority() int {
return 50
}
func init() {
option.RegisterHandler(&apiController{
cmd: flag.String("api", "", "Connect to a Trojan-Go API service. \"-api add/get/list\""),
address: flag.String("api-addr", "127.0.0.1:10000", "Address of Trojan-Go API service"),
password: flag.String("target-password", "", "Password of the target user"),
hash: flag.String("target-hash", "", "Hash of the target user"),
add: flag.Bool("add-profile", false, "Add a new profile with API"),
delete: flag.Bool("delete-profile", false, "Delete an existing profile with API"),
modify: flag.Bool("modify-profile", false, "Modify an existing profile with API"),
uploadSpeedLimit: flag.Int("upload-speed-limit", 0, "Limit the upload speed with API"),
downloadSpeedLimit: flag.Int("download-speed-limit", 0, "Limit the download speed with API"),
ipLimit: flag.Int("ip-limit", 0, "Limit the number of IP with API"),
ctx: context.Background(),
})
}