aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--salticidae.go75
-rw-r--r--stream.go88
-rw-r--r--test_msgnet/main.go145
-rw-r--r--test_msgnet/main_.go7
4 files changed, 309 insertions, 6 deletions
diff --git a/salticidae.go b/salticidae.go
index 1dce21e..ad80b88 100644
--- a/salticidae.go
+++ b/salticidae.go
@@ -13,6 +13,7 @@ import "unsafe"
type rawptr_t = unsafe.Pointer
+
type NetAddr = *C.struct_netaddr_t
func NewAddrFromIPPortString(addr string) (res NetAddr) {
@@ -22,26 +23,88 @@ func NewAddrFromIPPortString(addr string) (res NetAddr) {
return
}
-type MsgNetwork = *C.struct_msgnetwork_t
+func (self NetAddr) Free() { C.netaddr_free(self) }
type EventContext = *C.struct_eventcontext_t
func NewEventContext() EventContext { return C.eventcontext_new() }
+func (self EventContext) Free() { C.eventcontext_free(self) }
func (self EventContext) Dispatch() { C.eventcontext_dispatch(self) }
func (self EventContext) Stop() { C.eventcontext_stop(self) }
+type Opcode = uint8
+
+type Msg = *C.struct_msg_t
+
+func NewMsg(opcode Opcode, _moved_payload ByteArray) Msg {
+ return C.msg_new(C._opcode_t(opcode), _moved_payload)
+}
+
+func (self Msg) Free() { C.msg_free(self) }
+
+func (self Msg) GetPayload() DataStream {
+ return C.msg_get_payload(self)
+}
+
+func (self Msg) GetOpcode() Opcode {
+ return Opcode(C.msg_get_opcode(self))
+}
+
+type MsgNetworkInner = *C.struct_msgnetwork_t
+
+type MsgNetwork struct {
+ inner MsgNetworkInner
+}
+
+type MsgNetworkConn = *C.struct_msgnetwork_conn_t
+
+type MsgNetworkConnMode = C.msgnetwork_conn_mode_t
+
+
+func (self MsgNetworkConn) GetNet() MsgNetworkInner {
+ return C.msgnetwork_conn_get_net(self)
+}
+
+var (
+ CONN_MODE_ACTIVE = MsgNetworkConnMode(C.CONN_MODE_ACTIVE)
+ CONN_MODE_PASSIVE = MsgNetworkConnMode(C.CONN_MODE_PASSIVE)
+ CONN_MODE_DEAD = MsgNetworkConnMode(C.CONN_MODE_DEAD)
+)
+
+func (self MsgNetworkConn) GetMode() MsgNetworkConnMode {
+ return C.msgnetwork_conn_get_mode(self)
+}
+
+func (self MsgNetworkConn) GetAddr() NetAddr {
+ return C.msgnetwork_conn_get_addr(self)
+}
+
type MsgNetworkConfig = *C.struct_msgnetwork_config_t
func NewMsgNetworkConfig() MsgNetworkConfig { return C.msgnetwork_config_new() }
+func (self MsgNetworkConfig) Free() { C.msgnetwork_config_free(self) }
+
func NewMsgNetwork(ec EventContext, config MsgNetworkConfig) MsgNetwork {
- return C.msgnetwork_new(ec, config)
+ return MsgNetwork {
+ inner: C.msgnetwork_new(ec, config),
+ }
}
-func (self MsgNetwork) Start() { C.msgnetwork_start(self) }
-func (self MsgNetwork) Listen(addr NetAddr) { C.msgnetwork_listen(self, addr) }
-func (self MsgNetwork) Connect(addr NetAddr) { C.msgnetwork_connect(self, addr) }
-func (self MsgNetwork) Free() { C.msgnetwork_free(self) }
+func (self MsgNetwork) Free() { C.msgnetwork_free(self.inner) }
+func (self MsgNetwork) SendMsg(msg Msg, conn MsgNetworkConn) { self.inner.SendMsg(msg, conn) }
+func (self MsgNetwork) Connect(addr NetAddr) { self.inner.Connect(addr) }
+func (self MsgNetwork) Listen(addr NetAddr) { C.msgnetwork_listen(self.inner, addr) }
+func (self MsgNetwork) Start() { C.msgnetwork_start(self.inner) }
+func (self MsgNetwork) GetInner() MsgNetworkInner { return self.inner }
+
+func (self MsgNetworkInner) SendMsg(msg Msg, conn MsgNetworkConn) {
+ C.msgnetwork_send_msg(self, msg, conn)
+}
+
+func (self MsgNetworkInner) Connect(addr NetAddr) {
+ C.msgnetwork_connect(self, addr)
+}
type SigEvent = *C.sigev_t
type SigEventCallback = C.sigev_callback_t
diff --git a/stream.go b/stream.go
new file mode 100644
index 0000000..2727565
--- /dev/null
+++ b/stream.go
@@ -0,0 +1,88 @@
+package salticidae
+
+// #include "salticidae/stream.h"
+import "C"
+
+type ByteArray = *C.struct_bytearray_t
+
+func NewByteArray() ByteArray { return C.bytearray_new() }
+func (self ByteArray) Free() { C.bytearray_free(self) }
+
+type DataStream = *C.struct_datastream_t
+
+func NewDataStream() DataStream { return C.datastream_new() }
+func NewDataStreamFromBytes(bytes []byte) DataStream {
+ base := uintptr(rawptr_t(&bytes[0]))
+ return C.datastream_new_from_bytes(
+ (*C.uint8_t)(rawptr_t(base)),
+ (*C.uint8_t)(rawptr_t(base + uintptr(len(bytes)))))
+}
+
+func (self DataStream) Free() { C.datastream_free(self) }
+
+func (self DataStream) AssignByCopy(src DataStream) {
+ C.datastream_assign_by_copy(self, src)
+}
+
+func (self DataStream) AssignByMove(src DataStream) {
+ C.datastream_assign_by_move(self, src)
+}
+
+// TODO: datastream_data
+
+func (self DataStream) Clear() { C.datastream_clear(self) }
+
+func (self DataStream) Size() int { return int(C.datastream_size(self)) }
+
+func (self DataStream) PutU8(v uint8) { C.datastream_put_u8(self, C.uint8_t(v)) }
+func (self DataStream) PutU16(v uint16) { C.datastream_put_u16(self, C.uint16_t(v)) }
+func (self DataStream) PutU32(v uint32) { C.datastream_put_u32(self, C.uint32_t(v)) }
+func (self DataStream) PutU64(v uint32) { C.datastream_put_u64(self, C.uint64_t(v)) }
+
+func (self DataStream) PutI8(v int8) { C.datastream_put_i8(self, C.int8_t(v)) }
+func (self DataStream) PutI16(v int16) { C.datastream_put_i16(self, C.int16_t(v)) }
+func (self DataStream) PutI32(v int32) { C.datastream_put_i32(self, C.int32_t(v)) }
+func (self DataStream) PutI64(v int32) { C.datastream_put_i64(self, C.int64_t(v)) }
+
+func (self DataStream) PutData(bytes []byte) {
+ base := uintptr(rawptr_t(&bytes[0]))
+ C.datastream_put_data(self,
+ (*C.uint8_t)(rawptr_t(base)),
+ (*C.uint8_t)(rawptr_t(base + uintptr(len(bytes)))))
+
+}
+
+func (self DataStream) GetU8() uint8 { return uint8(C.datastream_get_u8(self)) }
+func (self DataStream) GetU16() uint16 { return uint16(C.datastream_get_u16(self)) }
+func (self DataStream) GetU32() uint32 { return uint32(C.datastream_get_u32(self)) }
+func (self DataStream) GetU64() uint64 { return uint64(C.datastream_get_u64(self)) }
+
+func (self DataStream) GetI8() int8 { return int8(C.datastream_get_i8(self)) }
+func (self DataStream) GetI16() int16 { return int16(C.datastream_get_i16(self)) }
+func (self DataStream) GetI32() int32 { return int32(C.datastream_get_i32(self)) }
+func (self DataStream) GetI64() int64 { return int64(C.datastream_get_i64(self)) }
+
+
+func (self DataStream) GetDataInPlace(length int) *C.uint8_t {
+ return C.datastream_get_data_inplace(self, C.size_t(length))
+}
+
+func (self DataStream) GetData(length int) []byte {
+ return C.GoBytes(rawptr_t(self.GetDataInPlace(length)), C.int(length))
+}
+
+type UInt256 = *C.uint256_t
+
+func NewUInt256() UInt256 { return C.uint256_new() }
+func (self UInt256) UInt256IsNull() bool { return bool(C.uint256_is_null(self)) }
+func (self UInt256) UInt256IsEq(other UInt256) bool { return bool(C.uint256_is_eq(self, other)) }
+func (self UInt256) Serialize(s DataStream) { C.uint256_serialize(self, s) }
+func (self UInt256) Unserialize(s DataStream) { C.uint256_unserialize(self, s) }
+
+func (self DataStream) GetHash() UInt256 {
+ return C.datastream_get_hash(self)
+}
+
+func (_moved_self DataStream) ToByteArray() ByteArray {
+ return C.datastream_to_bytearray(_moved_self)
+}
diff --git a/test_msgnet/main.go b/test_msgnet/main.go
new file mode 100644
index 0000000..b9a5048
--- /dev/null
+++ b/test_msgnet/main.go
@@ -0,0 +1,145 @@
+package main
+
+// void onTerm_cgo(int sig);
+import "C"
+
+import (
+ "unsafe"
+ "encoding/binary"
+ "fmt"
+ "salticidae-go"
+)
+
+var ec salticidae.EventContext
+const (
+ MSG_OPCODE_HELLO salticidae.Opcode = iota
+ MSG_OPCODE_ACK
+)
+
+//export onTerm
+func onTerm(_ int) {
+ ec.Stop()
+}
+
+type MsgHello struct {
+ name string
+ text string
+}
+
+func msgHelloSerialize(name string, text string) salticidae.Msg {
+ serialized := salticidae.NewDataStream()
+ t := make([]byte, 4)
+ binary.LittleEndian.PutUint32(t, uint32(len(name)))
+ serialized.PutData(t)
+ serialized.PutData([]byte(name))
+ serialized.PutData([]byte(text))
+ return salticidae.NewMsg(MSG_OPCODE_HELLO, serialized.ToByteArray())
+}
+
+func msgHelloUnserialize(msg salticidae.Msg) MsgHello {
+ p := msg.GetPayload()
+ length := binary.LittleEndian.Uint32(p.GetData(4))
+ name := string(p.GetData(int(length)))
+ text := string(p.GetData(p.Size()))
+ p.Free()
+ return MsgHello { name: name, text: text }
+}
+
+func msgAckSerialize() salticidae.Msg {
+ return salticidae.NewMsg(MSG_OPCODE_ACK, salticidae.NewByteArray())
+}
+
+type MyNet struct {
+ net salticidae.MsgNetwork
+ name string
+}
+
+var alice, bob MyNet
+
+func onReceiveHello(_msg salticidae.Msg, conn salticidae.MsgNetworkConn) {
+ net := conn.GetNet()
+ name := bob.name
+ if net == alice.net.GetInner() {
+ name = alice.name
+ }
+ msg := msgHelloUnserialize(_msg)
+ fmt.Printf("[%s] %s says %s\n", name, msg.name, msg.text)
+ ack := msgAckSerialize()
+ net.SendMsg(ack, conn)
+ ack.Free()
+}
+
+func onReceiveAck(msg salticidae.Msg, conn salticidae.MsgNetworkConn) {
+ net := conn.GetNet()
+ name := bob.name
+ if net == alice.net.GetInner() {
+ name = alice.name
+ }
+ fmt.Printf("[%s] the peer knows\n", name)
+}
+
+func connHandler(conn salticidae.MsgNetworkConn, connected bool) {
+ net := conn.GetNet()
+ n := &bob
+ if net == alice.net.GetInner() {
+ n = &alice
+ }
+ name := n.name
+ if connected {
+ if conn.GetMode() == salticidae.CONN_MODE_ACTIVE {
+ fmt.Printf("[%s] Connected, sending hello.", name)
+ hello := msgHelloSerialize(name, "Hello there!")
+ n.net.SendMsg(hello, conn)
+ hello.Free()
+ } else {
+ fmt.Printf("[%s] Accepted, waiting for greetings.\n", name)
+ }
+ } else {
+ fmt.Printf("[%s] Disconnected, retrying.\n", name)
+ net.Connect(conn.GetAddr())
+ }
+}
+
+func genMyNet(ec salticidae.EventContext, name string) MyNet {
+ netconfig := salticidae.NewMsgNetworkConfig()
+ n := MyNet {
+ net: salticidae.NewMsgNetwork(ec, netconfig),
+ name: name,
+ }
+ netconfig.Free()
+ return n
+}
+
+func main() {
+ ec = salticidae.NewEventContext()
+ alice_addr := salticidae.NewAddrFromIPPortString("127.0.0.1:12345")
+ bob_addr := salticidae.NewAddrFromIPPortString("127.0.0.1:12346")
+
+ alice := genMyNet(ec, "Alice")
+ bob := genMyNet(ec, "Bob")
+
+ alice.net.Start()
+ bob.net.Start()
+
+ alice.net.Listen(alice_addr)
+ bob.net.Listen(bob_addr)
+
+ alice.net.Connect(bob_addr)
+ bob.net.Connect(alice_addr)
+
+ alice_addr.Free()
+ bob_addr.Free()
+
+ ev_int := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(unsafe.Pointer(C.onTerm_cgo)))
+ ev_int.Add(salticidae.SIGINT)
+ ev_term := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(unsafe.Pointer(C.onTerm_cgo)))
+ ev_term.Add(salticidae.SIGTERM)
+
+ ec.Dispatch()
+
+ ev_int.Free()
+ ev_term.Free()
+ alice.net.Free()
+ bob.net.Free()
+ ec.Free()
+}
diff --git a/test_msgnet/main_.go b/test_msgnet/main_.go
new file mode 100644
index 0000000..2f53d93
--- /dev/null
+++ b/test_msgnet/main_.go
@@ -0,0 +1,7 @@
+package main
+
+// void onTerm_cgo(int sig) {
+// void onTerm(int);
+// onTerm(sig);
+// }
+import "C"