// package serv_rpc -- сервер RPC-запросов package serv_rpc import ( "fmt" "log" "net" "net/http" "net/rpc" "os" "wartank/pkg/types" ) type ServRpc struct { serv types.IServer } // NewServRpc -- возвращает новый сервер RPC-запросов func NewServRpc(serv types.IServer) (*ServRpc, error) { if serv == nil { return nil, fmt.Errorf("NewServRpc(): IServer==nil") } sf := &ServRpc{ serv: serv, } return sf, nil } // Run -- запускает сервис в работу func (sf *ServRpc) Run() { rpc.Register(sf) rpc.HandleHTTP() url := os.Getenv("SERVER_RPC_URL") if url == "" { log.Printf("ServRpc.Run(): env SERVER_RPC_URL not set\n") return } log.Printf("SERVER_RPC_URL=%v\n", url) lister, err := net.Listen("tcp", url) if err != nil { log.Printf("NewServRc(): listen error, err=\n\t%v\n", err) sf.serv.CancelApp() return } go http.Serve(lister, nil) } // EchoReq -- эхо запрос на сервер type EchoReq struct{} // EchoResp -- эхо ответ на запрос type EchoResp struct { Result string } // Echo -- эхо запрос для клиента func (sf *ServRpc) Echo(req *EchoReq, resp *EchoResp) error { log.Println("ServRpc.Echo()") resp.Result = "WarTank!" return nil } // LoginReq -- запрос на логин на сервер type LoginReq struct { Login string Pass string } // LoginResp -- ответ на запрос логина // // Вернёт ошибку если: // 1. Нужно создать админа // 2. Неверная пара логин/пароль type LoginResp struct { Result string } // Login -- запросвхода на сервер func (sf *ServRpc) Login(req *LoginReq, resp *LoginResp) error { log.Println("ServRpc.Login()") if !sf.checkUser(req.Login, req.Pass) { if err := sf.newUser(req.Login, req.Pass); err != nil { return fmt.Errorf("ServRpc.Login(): in create login(%q/%q), err=\n\t%w", req.Login, req.Pass, err) } } resp.Result = "ok" return nil } // Создаёт нового пользователя func (sf *ServRpc) newUser(login, pass string) error { log.Println("ServRpc.newUser()") if login == "" { return fmt.Errorf("ServRpc.newUser(): login is empty") } if pass == "" { return fmt.Errorf("ServRpc.newUser(): pass is empty") } store := sf.serv.Store() err := store.Put("/users/"+login, pass) if err != nil { return fmt.Errorf("ServRpc.newUser(): in create user, err=\n\t%w", err) } return nil } // AddBotReq -- запрос добавления бота на сервер type AddBotReq struct { Login string Pass string BotLogin string BotPass string } // AddBotResp -- ответ добавления бота на сервер type AddBotResp struct { Result string } // AddBot -- добавляет бота на сервер func (sf *ServRpc) AddBot(req *AddBotReq, resp *AddBotResp) error { log.Println("ServRpc.AddBot()") if !sf.checkUser(req.Login, req.Pass) { return fmt.Errorf("ServRpc.AddBot(): bad login/pass") } if !sf.checkBot(req.BotLogin, req.BotPass) { if err := sf.newBot(req.BotLogin, req.BotPass); err != nil { return fmt.Errorf("ServRpc.AddBot(): in save bot(%q/%q), err=\n\t%w", req.BotLogin, req.BotPass, err) } } resp.Result = "ok" return nil } // Создаёт нового бота по требованию func (sf *ServRpc) newBot(login, pass string) error { log.Println("ServRpc.newBot()") if login == "" { return fmt.Errorf("ServRpc.newBot(): login is empty") } if pass == "" { return fmt.Errorf("ServRpc.newBot(): pass is empty") } store := sf.serv.Store() err := store.Put("/bots/"+login, pass) if err != nil { return fmt.Errorf("ServRpc.newBot(): in create bot, err=\n\t%w", err) } return nil } // Проверяет наличие бота в базе func (sf *ServRpc) checkBot(login, pass string) bool { log.Println("ServRpc.checkBot()") store := sf.serv.Store() binData, err := store.Get("/bots/" + login) if err != nil { // Нет такого логина бота return false } strPass := string(binData) return pass == strPass } // Проверяет пользователя по логину/паролю func (sf *ServRpc) checkUser(login, pass string) bool { log.Println("ServRpc.checkUser()") store := sf.serv.Store() binData, err := store.Get("/users/" + login) if err != nil { // Нет такого логина return false } strPass := string(binData) return pass == strPass }