Skip to content

Commit

Permalink
Merge pull request #16 from teonet-go:feature/edit_text
Browse files Browse the repository at this point in the history
Feature/edit text
  • Loading branch information
kirill-scherba authored Nov 11, 2023
2 parents 4083775 + bacecd6 commit ef5395d
Show file tree
Hide file tree
Showing 22 changed files with 780 additions and 352 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@

# Docker builder
#
FROM golang:1.18.0 AS builder
FROM golang:1.21.3 AS builder

WORKDIR /go/src/github.com/teonet-go/teonet
# RUN apt update
Expand Down
39 changes: 0 additions & 39 deletions api.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,42 +355,3 @@ func (a API) MarshalBinary() (data []byte, err error) {
return
}

type APIDataAr struct {
name string // API (application) name
short string // API short name
long string // API decription (or long name)
version string // API version
Apis []APIData // API commands data
bslice.ByteSlice
}

// UnmarshalBinary binary unmarshal APIDataAr
func (a *APIDataAr) UnmarshalBinary(data []byte) (err error) {
var buf = bytes.NewBuffer(data)

if a.name, err = a.ReadString(buf); err != nil {
return
}
if a.short, err = a.ReadString(buf); err != nil {
return
}
if a.long, err = a.ReadString(buf); err != nil {
return
}
if a.version, err = a.ReadString(buf); err != nil {
return
}
var numCmds uint16
if err = binary.Read(buf, binary.LittleEndian, &numCmds); err != nil {
return
}
for i := 0; i < int(numCmds); i++ {
var api APIData
if err = api.UnmarshalBinary(buf); err != nil {
return
}
a.Apis = append(a.Apis, api)
}

return
}
234 changes: 147 additions & 87 deletions api_client.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2021-22 Kirill Scherba <kirill@scherba.ru>. All rights reserved.
// Copyright 2021-2023 Kirill Scherba <kirill@scherba.ru>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

Expand All @@ -7,25 +7,78 @@
package teonet

import (
"bytes"
"encoding/binary"
"errors"
"fmt"

"github.com/kirill-scherba/bslice"
)

const (
// Get server api command
CmdServerAPI = 255
// Get server api command
CmdClientAPI = 254
)

const (
FmtMsgCommandNotCount = "command '%s' not found"
)

var (
ErrWoronCommand = errors.New("wrong command")
)

// APIClient contains clients api data and receive methods
type APIClient struct {
APIDataAr
address string
cmdAPI byte
teo *Teonet
}
type APIDataAr struct {
name string // API (application) name
short string // API short name
long string // API decription (or long name)
version string // API version
Apis []APIData // API commands data
UserField interface{} // Some user field
bslice.ByteSlice
}

const (
// Get server api command
CmdServerAPI = 255
// Get server api command
CmdClientAPI = 254
)
// UnmarshalBinary binary unmarshal APIDataAr
func (a *APIDataAr) UnmarshalBinary(data []byte) (err error) {
var buf = bytes.NewBuffer(data)

// NewAPIClient create new APIClient
if a.name, err = a.ReadString(buf); err != nil {
return
}
if a.short, err = a.ReadString(buf); err != nil {
return
}
if a.long, err = a.ReadString(buf); err != nil {
return
}
if a.version, err = a.ReadString(buf); err != nil {
return
}
var numCmds uint16
if err = binary.Read(buf, binary.LittleEndian, &numCmds); err != nil {
return
}
for i := 0; i < int(numCmds); i++ {
var api APIData
if err = api.UnmarshalBinary(buf); err != nil {
return
}
a.Apis = append(a.Apis, api)
}

return
}

// NewAPIClient create new APIClient object
func (teo *Teonet) NewAPIClient(address string, cmdAPIs ...byte) (apicli *APIClient, err error) {
apicli = new(APIClient)
apicli.teo = teo
Expand All @@ -39,6 +92,21 @@ func (teo *Teonet) NewAPIClient(address string, cmdAPIs ...byte) (apicli *APICli
return
}

// SendTo sends api command.
func (api *APIClient) SendTo(command interface{}, data []byte,
waits ...func(data []byte, err error)) (id int, err error) {

cmd, err := api.GetCmd(command)
if err != nil {
return
}
id, err = api.teo.Command(cmd, data).SendTo(api.address)
if len(waits) > 0 {
go func() { waits[0](api.WaitFrom(cmd, uint32(id))) }()
}
return
}

// WaitFrom wait receiving data from peer. The third function parameter is
// timeout. It may be omitted or contain timeout time of time. Duration type.
// If timeout parameter is omitted than default timeout value sets to 2 second.
Expand All @@ -48,7 +116,7 @@ func (teo *Teonet) NewAPIClient(address string, cmdAPIs ...byte) (apicli *APICli
func (api *APIClient) WaitFrom(command interface{}, packetID ...interface{}) (data []byte, err error) {

// Get command number
cmd, err := api.getCmd(command)
cmd, err := api.GetCmd(command)
if err != nil {
return
}
Expand All @@ -63,7 +131,7 @@ func (api *APIClient) WaitFrom(command interface{}, packetID ...interface{}) (da
} else {
a, ok := api.AnswerMode(cmd)
if !ok {
err = errors.New("wrong command")
err = ErrWoronCommand
return
}
answerMode = a
Expand All @@ -83,24 +151,7 @@ func (api *APIClient) WaitFrom(command interface{}, packetID ...interface{}) (da
return
}

func (api *APIClient) SendTo(command interface{}, data []byte, waits ...func(data []byte, err error)) (id int, err error) {
cmd, err := api.getCmd(command)
if err != nil {
return
}
id, err = api.teo.Command(cmd, data).SendTo(api.address)
// TODO: i can't understand what does this code do :-)
// May be we need just call:
// api.teo.Command(cmd, data).SendTo(api.address, waits...)
// or in this case wee can lost cmd and id?
// Shure this code exactly than got answer with cmd and id in its data!!!
if len(waits) > 0 {
go func() { waits[0](api.WaitFrom(cmd, uint32(id))) }()
}
return
}

// Cmd get command number by name
// Cmd get command number by name.
func (api *APIClient) Cmd(name string) (cmd byte, ok bool) {
for i := range api.Apis {
if api.Apis[i].name == name {
Expand All @@ -112,7 +163,7 @@ func (api *APIClient) Cmd(name string) (cmd byte, ok bool) {
return
}

// Return get return parameter by cmd number or name
// Return get return parameter by cmd number or name.
func (api *APIClient) Return(command interface{}) (ret string, ok bool) {
a, ok := api.apiData(command)
if ok {
Expand All @@ -121,7 +172,7 @@ func (api *APIClient) Return(command interface{}) (ret string, ok bool) {
return
}

// AnswerMode get answer mode parameter by cmd number or name
// AnswerMode get answer mode parameter by cmd number or name.
func (api *APIClient) AnswerMode(command interface{}) (ret APIanswerMode, ok bool) {
a, ok := api.apiData(command)
if ok {
Expand All @@ -130,67 +181,13 @@ func (api *APIClient) AnswerMode(command interface{}) (ret APIanswerMode, ok boo
return
}

// apiData get return pointer to APIData by cmd number or name
func (api *APIClient) apiData(command interface{}) (ret *APIData, ok bool) {
cmd, err := api.getCmd(command)
if err != nil {
return
}
for i := range api.Apis {
if api.Apis[i].cmd == cmd {
ret = &api.Apis[i]
ok = true
return
}
}
return
}

// getCmd check command type and return command number
func (api *APIClient) getCmd(command interface{}) (cmd byte, err error) {
switch v := command.(type) {
case byte:
cmd = v
case int:
cmd = byte(v)
case string:
var ok bool
cmd, ok = api.Cmd(v)
if !ok {
err = fmt.Errorf("command '%s' not found", v)
return
}
default:
panic("wrong type of 'command' argument")
}
return
}

// getApi send cmdAPI command and get answer with APIDataAr: all API definition
func (api *APIClient) getApi() (err error) {
api.SendTo(api.cmdAPI, nil)
data, err := api.WaitFrom(api.cmdAPI)
if err != nil {
log.Error.Println("can't get api data, err", err)
return
}

err = api.APIDataAr.UnmarshalBinary(data)
if err != nil {
log.Error.Println("can't unmarshal api data, err", err)
return
}

return
}

// String stringlify APIClient
// String stringlify APIClient, return same string as Help function.
func (api APIClient) String() (str string) {
str += api.Help(false)
return
}

// APIClient return APICient help in string
// APIClient return APICient help in string.
func (api APIClient) Help(short bool) (str string) {

// Name version and description
Expand Down Expand Up @@ -238,5 +235,68 @@ func (api APIClient) Help(short bool) (str string) {
return
}

// Address return APIClient address
// Address returns application address.
func (api APIClient) Address() string { return api.address }

// AppShort returns application short name.
func (api APIClient) AppShort() string { return api.short }

// AppName returns application name.
func (api APIClient) AppName() string { return api.name }

// AppLong returns application long name (description).
func (api APIClient) AppLong() string { return api.long }

// apiData get return pointer to APIData by cmd number or name.
func (api *APIClient) apiData(command interface{}) (ret *APIData, ok bool) {
cmd, err := api.GetCmd(command)
if err != nil {
return
}
for i := range api.Apis {
if api.Apis[i].cmd == cmd {
ret = &api.Apis[i]
ok = true
return
}
}
return
}

// GetCmd check command type and return command number.
func (api *APIClient) GetCmd(command interface{}) (cmd byte, err error) {
switch v := command.(type) {
case byte:
cmd = v
case int:
cmd = byte(v)
case string:
var ok bool
cmd, ok = api.Cmd(v)
if !ok {
err = fmt.Errorf(FmtMsgCommandNotCount, v)
return
}
default:
panic("wrong type of 'command' argument")
}
return
}

// getApi send cmdAPI command and get answer with APIDataAr: all API definition.
func (api *APIClient) getApi() (err error) {
api.SendTo(api.cmdAPI, nil)
data, err := api.WaitFrom(api.cmdAPI)
if err != nil {
log.Error.Println("can't get api data, err", err)
return
}

err = api.APIDataAr.UnmarshalBinary(data)
if err != nil {
log.Error.Println("can't unmarshal api data, err", err)
return
}

return
}
19 changes: 19 additions & 0 deletions cmd/teoapi/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module github.com/teonet-go/teonet/cmd/teoapi

go 1.21.1

replace github.com/teonet-go/teonet => ../..

require (
github.com/teonet-go/teomon v0.5.14
github.com/teonet-go/teonet v0.6.4
)

require (
github.com/denisbrodbeck/machineid v1.0.1 // indirect
github.com/google/uuid v1.4.0 // indirect
github.com/kirill-scherba/bslice v0.0.2 // indirect
github.com/kirill-scherba/stable v0.0.8 // indirect
github.com/teonet-go/tru v0.0.18 // indirect
golang.org/x/sys v0.14.0 // indirect
)
Loading

0 comments on commit ef5395d

Please sign in to comment.