Compare commits
7 Commits
00f55788c2
...
5d5ee9c644
| Author | SHA1 | Date | |
|---|---|---|---|
| 5d5ee9c644 | |||
| 62e3c7814c | |||
| 9bad4d68f1 | |||
| b514c0d621 | |||
| c5e2e0f993 | |||
| f0753c5113 | |||
| 19fa5983d6 |
@ -1,19 +1,38 @@
|
|||||||
package hopp
|
package hopp
|
||||||
|
|
||||||
import "io"
|
import "net"
|
||||||
|
// import "time"
|
||||||
|
|
||||||
// Conn is a HOPP connection.
|
// Conn is a HOPP connection.
|
||||||
type Conn interface {
|
type Conn interface {
|
||||||
io.Closer
|
// Close closes the connection. Any blocked operations on the connection
|
||||||
|
// or its transactions will be unblocked and return errors.
|
||||||
|
Close() error
|
||||||
|
|
||||||
|
// See documentation for [net.Conn]
|
||||||
|
LocalAddr() net.Addr
|
||||||
|
RemoteAddr() net.Addr
|
||||||
|
|
||||||
|
// OpenTrans opens a transaction. The other party will not know about
|
||||||
|
// this until the first message is sent.
|
||||||
OpenTrans() (Trans, error)
|
OpenTrans() (Trans, error)
|
||||||
|
// AcceptTrans accepts a transaction from the other party. This must
|
||||||
|
// be called in a loop to avoid the connection locking up.
|
||||||
AcceptTrans() (Trans, error)
|
AcceptTrans() (Trans, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trans is a HOPP transaction.
|
// Trans is a HOPP transaction.
|
||||||
type Trans interface {
|
type Trans interface {
|
||||||
io.Closer
|
// Close closes the transaction. Any blocked operations will be
|
||||||
|
// unblocked and return errors.
|
||||||
|
Close() error
|
||||||
|
|
||||||
|
// ID returns the transaction ID. This must not change, and it must be
|
||||||
|
// unique within the connection.
|
||||||
ID() int64
|
ID() int64
|
||||||
|
|
||||||
|
// TODO: add methods for setting send and receive deadlines
|
||||||
|
|
||||||
// Send sends a message.
|
// Send sends a message.
|
||||||
Send(method uint16, data []byte) error
|
Send(method uint16, data []byte) error
|
||||||
// Receive receives a message.
|
// Receive receives a message.
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package generate
|
|||||||
import "io"
|
import "io"
|
||||||
import "fmt"
|
import "fmt"
|
||||||
import "bufio"
|
import "bufio"
|
||||||
|
import "strings"
|
||||||
|
|
||||||
const send =
|
const send =
|
||||||
`// Send sends one message along a transaction.
|
`// Send sends one message along a transaction.
|
||||||
@ -62,7 +63,6 @@ func (this *Protocol) Generate(writer io.Writer, packag string) error {
|
|||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,13 +86,13 @@ func (this *Protocol) receive(out io.Writer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *Protocol) defineMessage(out io.Writer, message Message) error {
|
func (this *Protocol) defineMessage(out io.Writer, message Message) error {
|
||||||
fmt.Fprintf(out, "// (%d) %s\n", message.Method, message.Doc)
|
fmt.Fprintln(out, comment("//", fmt.Sprintf("(%d) %s\n", message.Method, message.Doc)))
|
||||||
fmt.Fprintf(out, "type Message%s struct {\n", message.Name)
|
fmt.Fprintf(out, "type Message%s struct {\n", message.Name)
|
||||||
for _, field := range message.Fields {
|
for _, field := range message.Fields {
|
||||||
typ, err := this.ResolveType(field.Type)
|
typ, err := this.ResolveType(field.Type)
|
||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
if field.Doc != "" {
|
if field.Doc != "" {
|
||||||
fmt.Fprintf(out, "\t// %s\n", field.Doc)
|
fmt.Fprintf(out, "\t%s\n", comment("\t//", field.Doc))
|
||||||
}
|
}
|
||||||
if field.Optional {
|
if field.Optional {
|
||||||
typ = fmt.Sprintf("hopp.Option[%s]", typ)
|
typ = fmt.Sprintf("hopp.Option[%s]", typ)
|
||||||
@ -222,6 +222,12 @@ func (this *Protocol) unmarshalMessage(out io.Writer, message Message) error {
|
|||||||
fmt.Fprintf(out,
|
fmt.Fprintf(out,
|
||||||
"func (msg *Message%s) UnmarshalBinary(buffer []byte) error {\n",
|
"func (msg *Message%s) UnmarshalBinary(buffer []byte) error {\n",
|
||||||
message.Name)
|
message.Name)
|
||||||
|
if len(message.Fields) < 1 {
|
||||||
|
fmt.Fprintf(out, "\t// no fields\n")
|
||||||
|
fmt.Fprintf(out, "\treturn nil\n")
|
||||||
|
fmt.Fprintf(out, "}\n\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
fmt.Fprintf(out, "\tpairs, err := tape.DecodePairs(buffer)\n")
|
fmt.Fprintf(out, "\tpairs, err := tape.DecodePairs(buffer)\n")
|
||||||
fmt.Fprintf(out, "\tif err != nil { return err }\n")
|
fmt.Fprintf(out, "\tif err != nil { return err }\n")
|
||||||
requiredTotal := 0
|
requiredTotal := 0
|
||||||
@ -243,10 +249,12 @@ func (this *Protocol) unmarshalMessage(out io.Writer, message Message) error {
|
|||||||
fmt.Fprintf(out, "\n")
|
fmt.Fprintf(out, "\n")
|
||||||
fmt.Fprintf(out, "\t\t\tif err != nil { return err }\n")
|
fmt.Fprintf(out, "\t\t\tif err != nil { return err }\n")
|
||||||
if field.Optional {
|
if field.Optional {
|
||||||
fmt.Fprintf(out, "\t\t\tmsg.%s.Set(value)\n", field.Name)
|
fmt.Fprintf(out, "\t\t\tmsg.%s = hopp.O(value)\n", field.Name)
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(out, "\t\t\tmsg.%s = value\n", field.Name)
|
fmt.Fprintf(out, "\t\t\tmsg.%s = value\n", field.Name)
|
||||||
fmt.Fprintf(out, "\t\t\tfoundRequired ++\n")
|
if requiredTotal > 0 {
|
||||||
|
fmt.Fprintf(out, "\t\t\tfoundRequired ++\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Fprintf(out, "\t\t}\n")
|
fmt.Fprintf(out, "\t\t}\n")
|
||||||
@ -288,3 +296,7 @@ func (this *Protocol) unmarshalField(out io.Writer, field Field) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func comment(prefix, text string) string {
|
||||||
|
return prefix + " " + strings.ReplaceAll(strings.TrimSpace(text), "\n", "\n" + prefix + " ")
|
||||||
|
}
|
||||||
|
|||||||
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module git.tebibyte.media/sashakoshka/hopp
|
|||||||
go 1.23.0
|
go 1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.tebibyte.media/sashakoshka/go-util v0.8.0
|
git.tebibyte.media/sashakoshka/go-util v0.9.0
|
||||||
github.com/gomarkdown/markdown v0.0.0-20241205020045-f7e15b2f3e62
|
github.com/gomarkdown/markdown v0.0.0-20241205020045-f7e15b2f3e62
|
||||||
github.com/quic-go/quic-go v0.48.2
|
github.com/quic-go/quic-go v0.48.2
|
||||||
)
|
)
|
||||||
|
|||||||
4
go.sum
4
go.sum
@ -1,5 +1,5 @@
|
|||||||
git.tebibyte.media/sashakoshka/go-util v0.8.0 h1:XFuZ8HQkrnibrV016rso00geCFPatKpX4jxkIVhZPaQ=
|
git.tebibyte.media/sashakoshka/go-util v0.9.0 h1:s4u6USI1yRqTFNv52qJlEy1qO9pfF2+U6IklxkSLckY=
|
||||||
git.tebibyte.media/sashakoshka/go-util v0.8.0/go.mod h1:0Q1t+PePdx6tFYkRuJNcpM1Mru7wE6X+it1kwuOH+6Y=
|
git.tebibyte.media/sashakoshka/go-util v0.9.0/go.mod h1:0Q1t+PePdx6tFYkRuJNcpM1Mru7wE6X+it1kwuOH+6Y=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
|
|||||||
12
metadapta.go
12
metadapta.go
@ -46,6 +46,14 @@ func (this *a) Close() error {
|
|||||||
return this.underlying.Close()
|
return this.underlying.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *a) LocalAddr() net.Addr {
|
||||||
|
return this.underlying.LocalAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *a) RemoteAddr() net.Addr {
|
||||||
|
return this.underlying.RemoteAddr()
|
||||||
|
}
|
||||||
|
|
||||||
func (this *a) OpenTrans() (Trans, error) {
|
func (this *a) OpenTrans() (Trans, error) {
|
||||||
this.transLock.Lock()
|
this.transLock.Lock()
|
||||||
defer this.transLock.Unlock()
|
defer this.transLock.Unlock()
|
||||||
@ -85,10 +93,6 @@ func (this *a) sendMessageSafe(trans int64, method uint16, data []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *a) receive() {
|
func (this *a) receive() {
|
||||||
// TODO: multiplex receiving
|
|
||||||
// if a received transaction has a malformed ID, reject it here and
|
|
||||||
// cause the connection to fail
|
|
||||||
// at the end of this function, close all incoming channels
|
|
||||||
defer func() {
|
defer func() {
|
||||||
this.underlying.Close()
|
this.underlying.Close()
|
||||||
this.transLock.Lock()
|
this.transLock.Lock()
|
||||||
|
|||||||
11
metadaptb.go
11
metadaptb.go
@ -23,6 +23,14 @@ func (this *b) Close() error {
|
|||||||
return this.underlying.Close()
|
return this.underlying.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *b) LocalAddr() net.Addr {
|
||||||
|
return this.underlying.LocalAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *b) RemoteAddr() net.Addr {
|
||||||
|
return this.underlying.RemoteAddr()
|
||||||
|
}
|
||||||
|
|
||||||
func (this *b) OpenTrans() (Trans, error) {
|
func (this *b) OpenTrans() (Trans, error) {
|
||||||
stream, err := this.underlying.OpenStream()
|
stream, err := this.underlying.OpenStream()
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
@ -55,7 +63,8 @@ func (trans transB) Receive() (uint16, []byte, error) {
|
|||||||
return decodeMessageB(trans.underlying)
|
return decodeMessageB(trans.underlying)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MultiConn represens a multiplexed stream-oriented transport for use in [B].
|
// MultiConn represens a multiplexed stream-oriented transport for use in
|
||||||
|
// [AdaptB].
|
||||||
type MultiConn interface {
|
type MultiConn interface {
|
||||||
// See documentation for [net.Conn].
|
// See documentation for [net.Conn].
|
||||||
io.Closer
|
io.Closer
|
||||||
|
|||||||
16
option.go
16
option.go
@ -6,14 +6,18 @@ import "git.tebibyte.media/sashakoshka/go-util/container"
|
|||||||
// TODO make generic alias once go 1.24 releases
|
// TODO make generic alias once go 1.24 releases
|
||||||
type Option[T any] ucontainer.Optional[T]
|
type Option[T any] ucontainer.Optional[T]
|
||||||
|
|
||||||
func (option *Option[T]) Get() (T, bool) {
|
func O[T any](value T) Option[T] {
|
||||||
return option.Get()
|
return Option[T](ucontainer.O(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (option *Option[T]) Set(value T) {
|
func Void[T any]() Option[T] {
|
||||||
option.Set(value)
|
return Option[T](ucontainer.Void[T]())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (option *Option[T]) Reset() {
|
func (option Option[T]) Ok() bool {
|
||||||
option.Reset()
|
return (ucontainer.Optional[T])(option).Exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (option Option[T]) Get() (T, bool) {
|
||||||
|
return (ucontainer.Optional[T])(option).Value()
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user