examples/chat: Make chat example compile
This commit is contained in:
parent
e5d7ad0702
commit
14a317c2ab
@ -17,8 +17,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
address := os.Args[1]
|
address := os.Args[1]
|
||||||
room := os.Args[2]
|
room := os.Args[2]
|
||||||
var nickname hopp.Option[string]; if len(os.Args) >= 4 {
|
nickname := "Anonymous"; if len(os.Args) >= 4 {
|
||||||
nickname = hopp.O(os.Args[3])
|
nickname = os.Args[3]
|
||||||
}
|
}
|
||||||
trans, err := join(address, room, nickname)
|
trans, err := join(address, room, nickname)
|
||||||
handleErr(1, err)
|
handleErr(1, err)
|
||||||
@ -31,15 +31,11 @@ func main() {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for {
|
for {
|
||||||
message, err := chat.Receive(trans)
|
message, _, err := chat.Receive(trans)
|
||||||
handleErr(1, err)
|
handleErr(1, err)
|
||||||
switch message := message.(type) {
|
switch message := message.(type) {
|
||||||
case *chat.MessageChat:
|
case *chat.MessageChat:
|
||||||
nickname := "Anonymous"
|
fmt.Fprintf(os.Stdout, "%s: %s\n", message.Nickname, message.Content)
|
||||||
if value, ok := message.Nickname.Get(); ok {
|
|
||||||
nickname = value
|
|
||||||
}
|
|
||||||
fmt.Fprintf(os.Stdout, "%s: %s\n", nickname, message.Content)
|
|
||||||
case *chat.MessageJoinNotify:
|
case *chat.MessageJoinNotify:
|
||||||
fmt.Fprintf(os.Stdout, "(i) %s joined the room\n", message.Nickname)
|
fmt.Fprintf(os.Stdout, "(i) %s joined the room\n", message.Nickname)
|
||||||
case *chat.MessageLeaveNotify:
|
case *chat.MessageLeaveNotify:
|
||||||
@ -48,7 +44,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func join(address string, room string, nickname hopp.Option[string]) (hopp.Trans, error) {
|
func join(address string, room string, nickname string) (hopp.Trans, error) {
|
||||||
ctx, done := context.WithTimeout(context.Background(), 16 * time.Second)
|
ctx, done := context.WithTimeout(context.Background(), 16 * time.Second)
|
||||||
defer done()
|
defer done()
|
||||||
dialer := hopp.Dialer {
|
dialer := hopp.Dialer {
|
||||||
@ -57,41 +53,24 @@ func join(address string, room string, nickname hopp.Option[string]) (hopp.Trans
|
|||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
conn, err := dialer.Dial(ctx, "quic", address)
|
conn, err := dialer.Dial(ctx, "tcp", address)
|
||||||
if err != nil { return nil, err }
|
|
||||||
|
|
||||||
err = updateProfile(conn, nickname)
|
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
|
|
||||||
transRoom, err := conn.OpenTrans()
|
transRoom, err := conn.OpenTrans()
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
err = chat.Send(transRoom, &chat.MessageJoin {
|
_, err = chat.Send(transRoom, &chat.MessageJoin {
|
||||||
Room: room,
|
Room: room,
|
||||||
|
Nickname: nickname,
|
||||||
})
|
})
|
||||||
if err != nil { return nil, err }
|
if err != nil { return nil, err }
|
||||||
return transRoom, nil
|
return transRoom, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func send(trans hopp.Trans, content string) error {
|
func send(trans hopp.Trans, content string) error {
|
||||||
return chat.Send(trans, &chat.MessageChat {
|
_, err := chat.Send(trans, &chat.MessageChat {
|
||||||
Content: content,
|
Content: content,
|
||||||
})
|
})
|
||||||
}
|
return err
|
||||||
|
|
||||||
func updateProfile(conn hopp.Conn, nickname hopp.Option[string]) error {
|
|
||||||
trans, err := conn.OpenTrans()
|
|
||||||
if err != nil { return err }
|
|
||||||
defer trans.Close()
|
|
||||||
err = chat.Send(trans, &chat.MessageUpdateProfile {
|
|
||||||
Nickname: nickname,
|
|
||||||
})
|
|
||||||
if err != nil { return err }
|
|
||||||
message, err := chat.Receive(trans)
|
|
||||||
if err != nil { return err }
|
|
||||||
switch message := message.(type) {
|
|
||||||
case *chat.MessageError: return message
|
|
||||||
default: return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleErr(code int, err error) {
|
func handleErr(code int, err error) {
|
||||||
|
|||||||
@ -2,5 +2,5 @@
|
|||||||
// source files, run this command from within the root directory of the
|
// source files, run this command from within the root directory of the
|
||||||
// repository:
|
// repository:
|
||||||
//
|
//
|
||||||
// go run ./cmd/hopp-generate examples/chat/protocol.md examples/chat/protocol
|
// go run ./cmd/hopp-generate examples/chat/protocol.pdl -o examples/chat/protocol/protocol.go
|
||||||
package chat
|
package chat
|
||||||
|
|||||||
@ -3,8 +3,8 @@ package chat
|
|||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func (msg *MessageError) Error() string {
|
func (msg *MessageError) Error() string {
|
||||||
if description, ok := msg.Description.Get(); ok {
|
if description, ok := msg.Description.Value(); ok {
|
||||||
return fmt.Sprintf("other party sent error: %d %s", msg.Error, description)
|
return fmt.Sprintf("other party sent error: %d %s", msg.Code, description)
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("other party sent error: %d", msg.Code)
|
return fmt.Sprintf("other party sent error: %d", msg.Code)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,15 @@ type Message interface {
|
|||||||
Method() uint16
|
Method() uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send encodes a message and sends it along a transaction.
|
||||||
|
func Send(trans hopp.Trans, message Message) (n int, err error) {
|
||||||
|
writer, err := trans.SendWriter(message.Method())
|
||||||
|
if err != nil { return n, err }
|
||||||
|
defer writer.Close()
|
||||||
|
encoder := tape.NewEncoder(writer)
|
||||||
|
return message.Encode(encoder)
|
||||||
|
}
|
||||||
|
|
||||||
// canAssign determines if data from the given source tag can be assigned to
|
// canAssign determines if data from the given source tag can be assigned to
|
||||||
// a Go type represented by destination. It is designed to receive destination
|
// a Go type represented by destination. It is designed to receive destination
|
||||||
// values from [generate.Generator.generateCanAssign]. The eventual Go type and
|
// values from [generate.Generator.generateCanAssign]. The eventual Go type and
|
||||||
@ -225,7 +234,7 @@ func(this *MessageJoin) Decode(decoder *tape.Decoder) (n int, err error) {
|
|||||||
// must be sent within a room transaction.
|
// must be sent within a room transaction.
|
||||||
type MessageChat struct {
|
type MessageChat struct {
|
||||||
Content string
|
Content string
|
||||||
Nickname hopp.Option[string]
|
Nickname string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method returns the message's method number.
|
// Method returns the message's method number.
|
||||||
@ -242,36 +251,34 @@ func(this *MessageChat) Encode(encoder *tape.Encoder) (n int, err error) {
|
|||||||
nn, err = encoder.WriteUintN(2, tag_8.CN() + 1)
|
nn, err = encoder.WriteUintN(2, tag_8.CN() + 1)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
{
|
{
|
||||||
|
nn, err = encoder.WriteUint16(0x0001)
|
||||||
|
n += nn; if err != nil { return n, err }
|
||||||
|
tag_9 := tape.StringTag(string((*this).Nickname))
|
||||||
|
nn, err = encoder.WriteUint8(uint8(tag_9))
|
||||||
|
n += nn; if err != nil { return n, err }
|
||||||
|
if len((*this).Nickname) > tape.MaxStructureLength {
|
||||||
|
return n, tape.ErrTooLong
|
||||||
|
}
|
||||||
|
if tag_9.Is(tape.LBA) {
|
||||||
|
nn, err = encoder.WriteUintN(uint64(len((*this).Nickname)), tag_9.CN())
|
||||||
|
n += nn; if err != nil { return n, err }
|
||||||
|
}
|
||||||
|
nn, err = encoder.Write([]byte((*this).Nickname))
|
||||||
|
n += nn; if err != nil { return n, err }
|
||||||
nn, err = encoder.WriteUint16(0x0000)
|
nn, err = encoder.WriteUint16(0x0000)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
tag_9 := tape.StringTag(string((*this).Content))
|
tag_10 := tape.StringTag(string((*this).Content))
|
||||||
nn, err = encoder.WriteUint8(uint8(tag_9))
|
nn, err = encoder.WriteUint8(uint8(tag_10))
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
if len((*this).Content) > tape.MaxStructureLength {
|
if len((*this).Content) > tape.MaxStructureLength {
|
||||||
return n, tape.ErrTooLong
|
return n, tape.ErrTooLong
|
||||||
}
|
}
|
||||||
if tag_9.Is(tape.LBA) {
|
if tag_10.Is(tape.LBA) {
|
||||||
nn, err = encoder.WriteUintN(uint64(len((*this).Content)), tag_9.CN())
|
nn, err = encoder.WriteUintN(uint64(len((*this).Content)), tag_10.CN())
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
}
|
}
|
||||||
nn, err = encoder.Write([]byte((*this).Content))
|
nn, err = encoder.Write([]byte((*this).Content))
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
if value, ok := (*this).Nickname.Value(); ok {
|
|
||||||
nn, err = encoder.WriteUint16(0x0001)
|
|
||||||
n += nn; if err != nil { return n, err }
|
|
||||||
tag_10 := tape.StringTag(string(value))
|
|
||||||
nn, err = encoder.WriteUint8(uint8(tag_10))
|
|
||||||
n += nn; if err != nil { return n, err }
|
|
||||||
if len(value) > tape.MaxStructureLength {
|
|
||||||
return n, tape.ErrTooLong
|
|
||||||
}
|
|
||||||
if tag_10.Is(tape.LBA) {
|
|
||||||
nn, err = encoder.WriteUintN(uint64(len(value)), tag_10.CN())
|
|
||||||
n += nn; if err != nil { return n, err }
|
|
||||||
}
|
|
||||||
nn, err = encoder.Write([]byte(value))
|
|
||||||
n += nn; if err != nil { return n, err }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
@ -573,22 +580,20 @@ func decodeBranch_5c1cf9347bb6d9f41cee64b186392d24_MessageChat(this *MessageChat
|
|||||||
tape.Skim(decoder, fieldTag_31)
|
tape.Skim(decoder, fieldTag_31)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var destination_33 string
|
var length_33 uint64
|
||||||
var length_34 uint64
|
|
||||||
if fieldTag_31.Is(tape.LBA) {
|
if fieldTag_31.Is(tape.LBA) {
|
||||||
length_34, nn, err = decoder.ReadUintN(int(fieldTag_31.CN()))
|
length_33, nn, err = decoder.ReadUintN(int(fieldTag_31.CN()))
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
} else {
|
} else {
|
||||||
length_34 = uint64(fieldTag_31.CN())
|
length_33 = uint64(fieldTag_31.CN())
|
||||||
}
|
}
|
||||||
if length_34 > uint64(tape.MaxStructureLength) {
|
if length_33 > uint64(tape.MaxStructureLength) {
|
||||||
return n, tape.ErrTooLong
|
return n, tape.ErrTooLong
|
||||||
}
|
}
|
||||||
buffer := make([]byte, length_34)
|
buffer := make([]byte, length_33)
|
||||||
nn, err = decoder.Read(buffer)
|
nn, err = decoder.Read(buffer)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
*(&destination_33) = string(buffer)
|
*(&(this.Nickname)) = string(buffer)
|
||||||
this.Nickname = hopp.O(destination_33)
|
|
||||||
default:
|
default:
|
||||||
tape.Skim(decoder, fieldTag_31)
|
tape.Skim(decoder, fieldTag_31)
|
||||||
continue
|
continue
|
||||||
@ -599,41 +604,41 @@ func decodeBranch_5c1cf9347bb6d9f41cee64b186392d24_MessageChat(this *MessageChat
|
|||||||
|
|
||||||
func decodeBranch_68c536511e6d598462efc482144438e9_MessageJoinNotify(this *MessageJoinNotify, decoder *tape.Decoder, tag tape.Tag) (n int, err error) {
|
func decodeBranch_68c536511e6d598462efc482144438e9_MessageJoinNotify(this *MessageJoinNotify, decoder *tape.Decoder, tag tape.Tag) (n int, err error) {
|
||||||
var nn int
|
var nn int
|
||||||
var length_35 uint64
|
var length_34 uint64
|
||||||
if length_35 > uint64(tape.MaxStructureLength) {
|
if length_34 > uint64(tape.MaxStructureLength) {
|
||||||
return n, tape.ErrTooLong
|
return n, tape.ErrTooLong
|
||||||
}
|
}
|
||||||
length_35, nn, err = decoder.ReadUintN(int(tag.CN()) + 1)
|
length_34, nn, err = decoder.ReadUintN(int(tag.CN()) + 1)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
for _ = range length_35 {
|
for _ = range length_34 {
|
||||||
var fieldKey_36 uint16
|
var fieldKey_35 uint16
|
||||||
fieldKey_36, nn, err = decoder.ReadUint16()
|
fieldKey_35, nn, err = decoder.ReadUint16()
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
var fieldTag_37 tape.Tag
|
var fieldTag_36 tape.Tag
|
||||||
fieldTag_37, nn, err = decoder.ReadTag()
|
fieldTag_36, nn, err = decoder.ReadTag()
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
switch fieldKey_36 {
|
switch fieldKey_35 {
|
||||||
case 0x0000:
|
case 0x0000:
|
||||||
if !(canAssign(tape.LBA, fieldTag_37)) {
|
if !(canAssign(tape.LBA, fieldTag_36)) {
|
||||||
tape.Skim(decoder, fieldTag_37)
|
tape.Skim(decoder, fieldTag_36)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var length_38 uint64
|
var length_37 uint64
|
||||||
if fieldTag_37.Is(tape.LBA) {
|
if fieldTag_36.Is(tape.LBA) {
|
||||||
length_38, nn, err = decoder.ReadUintN(int(fieldTag_37.CN()))
|
length_37, nn, err = decoder.ReadUintN(int(fieldTag_36.CN()))
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
} else {
|
} else {
|
||||||
length_38 = uint64(fieldTag_37.CN())
|
length_37 = uint64(fieldTag_36.CN())
|
||||||
}
|
}
|
||||||
if length_38 > uint64(tape.MaxStructureLength) {
|
if length_37 > uint64(tape.MaxStructureLength) {
|
||||||
return n, tape.ErrTooLong
|
return n, tape.ErrTooLong
|
||||||
}
|
}
|
||||||
buffer := make([]byte, length_38)
|
buffer := make([]byte, length_37)
|
||||||
nn, err = decoder.Read(buffer)
|
nn, err = decoder.Read(buffer)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
*(&(this.Nickname)) = string(buffer)
|
*(&(this.Nickname)) = string(buffer)
|
||||||
default:
|
default:
|
||||||
tape.Skim(decoder, fieldTag_37)
|
tape.Skim(decoder, fieldTag_36)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -642,43 +647,84 @@ func decodeBranch_68c536511e6d598462efc482144438e9_MessageJoinNotify(this *Messa
|
|||||||
|
|
||||||
func decodeBranch_68c536511e6d598462efc482144438e9_MessageLeaveNotify(this *MessageLeaveNotify, decoder *tape.Decoder, tag tape.Tag) (n int, err error) {
|
func decodeBranch_68c536511e6d598462efc482144438e9_MessageLeaveNotify(this *MessageLeaveNotify, decoder *tape.Decoder, tag tape.Tag) (n int, err error) {
|
||||||
var nn int
|
var nn int
|
||||||
var length_39 uint64
|
var length_38 uint64
|
||||||
if length_39 > uint64(tape.MaxStructureLength) {
|
if length_38 > uint64(tape.MaxStructureLength) {
|
||||||
return n, tape.ErrTooLong
|
return n, tape.ErrTooLong
|
||||||
}
|
}
|
||||||
length_39, nn, err = decoder.ReadUintN(int(tag.CN()) + 1)
|
length_38, nn, err = decoder.ReadUintN(int(tag.CN()) + 1)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
for _ = range length_39 {
|
for _ = range length_38 {
|
||||||
var fieldKey_40 uint16
|
var fieldKey_39 uint16
|
||||||
fieldKey_40, nn, err = decoder.ReadUint16()
|
fieldKey_39, nn, err = decoder.ReadUint16()
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
var fieldTag_41 tape.Tag
|
var fieldTag_40 tape.Tag
|
||||||
fieldTag_41, nn, err = decoder.ReadTag()
|
fieldTag_40, nn, err = decoder.ReadTag()
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
switch fieldKey_40 {
|
switch fieldKey_39 {
|
||||||
case 0x0000:
|
case 0x0000:
|
||||||
if !(canAssign(tape.LBA, fieldTag_41)) {
|
if !(canAssign(tape.LBA, fieldTag_40)) {
|
||||||
tape.Skim(decoder, fieldTag_41)
|
tape.Skim(decoder, fieldTag_40)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var length_42 uint64
|
var length_41 uint64
|
||||||
if fieldTag_41.Is(tape.LBA) {
|
if fieldTag_40.Is(tape.LBA) {
|
||||||
length_42, nn, err = decoder.ReadUintN(int(fieldTag_41.CN()))
|
length_41, nn, err = decoder.ReadUintN(int(fieldTag_40.CN()))
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
} else {
|
} else {
|
||||||
length_42 = uint64(fieldTag_41.CN())
|
length_41 = uint64(fieldTag_40.CN())
|
||||||
}
|
}
|
||||||
if length_42 > uint64(tape.MaxStructureLength) {
|
if length_41 > uint64(tape.MaxStructureLength) {
|
||||||
return n, tape.ErrTooLong
|
return n, tape.ErrTooLong
|
||||||
}
|
}
|
||||||
buffer := make([]byte, length_42)
|
buffer := make([]byte, length_41)
|
||||||
nn, err = decoder.Read(buffer)
|
nn, err = decoder.Read(buffer)
|
||||||
n += nn; if err != nil { return n, err }
|
n += nn; if err != nil { return n, err }
|
||||||
*(&(this.Nickname)) = string(buffer)
|
*(&(this.Nickname)) = string(buffer)
|
||||||
default:
|
default:
|
||||||
tape.Skim(decoder, fieldTag_41)
|
tape.Skim(decoder, fieldTag_40)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Receive decodes a message from a transaction and returns it as a value.
|
||||||
|
// Use a type switch to determine what type of message it is.
|
||||||
|
func Receive(trans hopp.Trans) (message any, n int, err error) {
|
||||||
|
method, reader, err := trans.ReceiveReader()
|
||||||
|
decoder := tape.NewDecoder(reader)
|
||||||
|
if err != nil { return nil, n, err }
|
||||||
|
switch method {
|
||||||
|
case 0001:
|
||||||
|
var message MessageSuccess
|
||||||
|
nn, err := message.Decode(decoder)
|
||||||
|
n += nn; if err != nil { return nil, n, err }
|
||||||
|
return message, n, nil
|
||||||
|
case 0200:
|
||||||
|
var message MessageJoin
|
||||||
|
nn, err := message.Decode(decoder)
|
||||||
|
n += nn; if err != nil { return nil, n, err }
|
||||||
|
return message, n, nil
|
||||||
|
case 0300:
|
||||||
|
var message MessageChat
|
||||||
|
nn, err := message.Decode(decoder)
|
||||||
|
n += nn; if err != nil { return nil, n, err }
|
||||||
|
return message, n, nil
|
||||||
|
case 0400:
|
||||||
|
var message MessageJoinNotify
|
||||||
|
nn, err := message.Decode(decoder)
|
||||||
|
n += nn; if err != nil { return nil, n, err }
|
||||||
|
return message, n, nil
|
||||||
|
case 0401:
|
||||||
|
var message MessageLeaveNotify
|
||||||
|
nn, err := message.Decode(decoder)
|
||||||
|
n += nn; if err != nil { return nil, n, err }
|
||||||
|
return message, n, nil
|
||||||
|
case 0000:
|
||||||
|
var message MessageError
|
||||||
|
nn, err := message.Decode(decoder)
|
||||||
|
n += nn; if err != nil { return nil, n, err }
|
||||||
|
return message, n, nil
|
||||||
|
}
|
||||||
|
return nil, n, hopp.ErrUnknownMethod
|
||||||
|
}
|
||||||
|
|||||||
@ -1,70 +0,0 @@
|
|||||||
# Chat Protocol
|
|
||||||
|
|
||||||
This document describes a simple chat protocol. To re-generate the source files,
|
|
||||||
run `go run ./cmd/hopp-generate examples/chat/protocol.md examples/chat/protocol`
|
|
||||||
|
|
||||||
## Messages
|
|
||||||
|
|
||||||
### 0000 Error
|
|
||||||
| Tag | Name | Type | Required |
|
|
||||||
| --: | ----------- | ------ | -------- |
|
|
||||||
| 0 | Code | U16 | Yes |
|
|
||||||
| 1 | Description | String | No |
|
|
||||||
|
|
||||||
Error is sent by a party when the other party has done something erroneous. The
|
|
||||||
valid error codes are:
|
|
||||||
|
|
||||||
- 0: General, unspecified error
|
|
||||||
|
|
||||||
The description field, if specified, determines a human-readable error to be
|
|
||||||
shown to the user. The sending party must immediately close the transaction
|
|
||||||
after this message is sent.
|
|
||||||
|
|
||||||
### 0001 Success
|
|
||||||
Success is sent by a party when it has successfully completed a task given to it
|
|
||||||
by the other party. The sending party must immediately close the transaction
|
|
||||||
after this message is sent.
|
|
||||||
|
|
||||||
### 0100 UpdateProfile
|
|
||||||
| Tag | Name | Type | Required |
|
|
||||||
| --: | -------- | ------ | -------- |
|
|
||||||
| 0 | Nickname | String | No |
|
|
||||||
|
|
||||||
UpdateProfile is sent by the client in a new transaction to update the profile
|
|
||||||
details that will be shown to other connected clients.
|
|
||||||
|
|
||||||
### 0200 Join
|
|
||||||
| Tag | Name | Type | Required |
|
|
||||||
| --: | -------- | ------ | -------- |
|
|
||||||
| 0 | Room | String | Yes |
|
|
||||||
|
|
||||||
Join is sent by the client when it wishes to join a room. It must begin a new
|
|
||||||
transaction, and that transaction will persist while the user is in that room.
|
|
||||||
Messages having to do with the room will be sent along this transaction. To
|
|
||||||
leave the room, the client must close the transaction.
|
|
||||||
|
|
||||||
### 0201 Chat
|
|
||||||
| Tag | Name | Type | Required |
|
|
||||||
| --: | -------- | ------ | -------- |
|
|
||||||
| 0 | Nickname | String | No |
|
|
||||||
| 1 | Content | String | Yes |
|
|
||||||
|
|
||||||
Chat is sent by the client when it wishes to post a message to the room. It is
|
|
||||||
also relayed by the server to other clients to notify them of the message. It
|
|
||||||
must be sent within a room transaction.
|
|
||||||
|
|
||||||
### 0300 JoinNotify
|
|
||||||
| Tag | Name | Type | Required |
|
|
||||||
| --: | -------- | ------ | -------- |
|
|
||||||
| 0 | Nickname | String | No |
|
|
||||||
|
|
||||||
JoinNotify is sent by the server when another client joins the room. It must be
|
|
||||||
sent within a room transaction.
|
|
||||||
|
|
||||||
### 0301 LeaveNotify
|
|
||||||
| Tag | Name | Type | Required |
|
|
||||||
| --: | -------- | ------ | -------- |
|
|
||||||
| 0 | Nickname | String | No |
|
|
||||||
|
|
||||||
LeaveNotify is sent by the server when another client leaves the room. It must
|
|
||||||
be sent within a room transaction.
|
|
||||||
@ -32,7 +32,7 @@ M0200 Join {
|
|||||||
// must be sent within a room transaction.
|
// must be sent within a room transaction.
|
||||||
M0300 Chat {
|
M0300 Chat {
|
||||||
0000 Content String,
|
0000 Content String,
|
||||||
0001 Nickname ?String,
|
0001 Nickname String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// JoinNotify is sent by the server when another client joins the room. It must be
|
// JoinNotify is sent by the server when another client joins the room. It must be
|
||||||
|
|||||||
@ -28,7 +28,7 @@ func main() {
|
|||||||
func host(address string, certPath, keyPath string) error {
|
func host(address string, certPath, keyPath string) error {
|
||||||
keyPair, err := tls.LoadX509KeyPair(certPath, keyPath)
|
keyPair, err := tls.LoadX509KeyPair(certPath, keyPath)
|
||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
listener, err := hopp.ListenQUIC("quic", address, &tls.Config {
|
listener, err := hopp.ListenTLS("tcp", address, &tls.Config {
|
||||||
InsecureSkipVerify: true,
|
InsecureSkipVerify: true,
|
||||||
Certificates: []tls.Certificate { keyPair },
|
Certificates: []tls.Certificate { keyPair },
|
||||||
})
|
})
|
||||||
@ -63,6 +63,7 @@ func (this *client) run() {
|
|||||||
log.Println("accepted transaction")
|
log.Println("accepted transaction")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("XXX %v failed: %v", this.conn.RemoteAddr(), err)
|
log.Printf("XXX %v failed: %v", this.conn.RemoteAddr(), err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
go this.runTrans(trans)
|
go this.runTrans(trans)
|
||||||
}
|
}
|
||||||
@ -70,7 +71,7 @@ func (this *client) run() {
|
|||||||
|
|
||||||
func (this *client) runTrans(trans hopp.Trans) {
|
func (this *client) runTrans(trans hopp.Trans) {
|
||||||
defer trans.Close()
|
defer trans.Close()
|
||||||
message, err := chat.Receive(trans)
|
message, _, err := chat.Receive(trans)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"XXX %v transaction failed: %v",
|
"XXX %v transaction failed: %v",
|
||||||
@ -97,7 +98,7 @@ func (this *client) transTalk(trans hopp.Trans, initial *chat.MessageJoin) error
|
|||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
defer this.leaveRoom(trans, room)
|
defer this.leaveRoom(trans, room)
|
||||||
for {
|
for {
|
||||||
message, err := chat.Receive(trans)
|
message, _, err := chat.Receive(trans)
|
||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
switch message := message.(type) {
|
switch message := message.(type) {
|
||||||
case *chat.MessageChat:
|
case *chat.MessageChat:
|
||||||
@ -110,7 +111,7 @@ func (this *client) transTalk(trans hopp.Trans, initial *chat.MessageJoin) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *client) handleMessageChat(trans hopp.Trans, room string, message *chat.MessageChat) error {
|
func (this *client) handleMessageChat(trans hopp.Trans, room string, message *chat.MessageChat) error {
|
||||||
log.Println("(). %s #%s: %s", this.nickname.Default("Anonymous"), room, message.Content)
|
log.Println("(). %s #%s: %s", this.nickname, room, message.Content)
|
||||||
clients, done := clients.RBorrow()
|
clients, done := clients.RBorrow()
|
||||||
defer done()
|
defer done()
|
||||||
for client := range clients {
|
for client := range clients {
|
||||||
@ -126,7 +127,7 @@ func (this *client) relayMessage(room string, message *chat.MessageChat) error {
|
|||||||
rooms, done := this.rooms.RBorrow()
|
rooms, done := this.rooms.RBorrow()
|
||||||
defer done()
|
defer done()
|
||||||
if trans, ok := rooms[room]; ok {
|
if trans, ok := rooms[room]; ok {
|
||||||
err := chat.Send(trans, message)
|
_, err := chat.Send(trans, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not relay message: %w", err)
|
return fmt.Errorf("could not relay message: %w", err)
|
||||||
}
|
}
|
||||||
@ -141,7 +142,7 @@ func (this *client) joinRoom(trans hopp.Trans, room string) error {
|
|||||||
return fmt.Errorf("already joined %s", room)
|
return fmt.Errorf("already joined %s", room)
|
||||||
}
|
}
|
||||||
rooms[room] = trans
|
rooms[room] = trans
|
||||||
log.Printf("--> user %s joined #%s", this.nickname.Default("Anonymous"), room)
|
log.Printf("--> user %s joined #%s", this.nickname, room)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +153,7 @@ func (this *client) leaveRoom(trans hopp.Trans, room string) error {
|
|||||||
return fmt.Errorf("not in %s", room)
|
return fmt.Errorf("not in %s", room)
|
||||||
}
|
}
|
||||||
delete(rooms, room)
|
delete(rooms, room)
|
||||||
log.Printf("<-- user %s left #%s", this.nickname.Default("Anonymous"), room)
|
log.Printf("<-- user %s left #%s", this.nickname, room)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user