diff options
-rw-r--r-- | Makefile | 35 | ||||
-rw-r--r-- | scripts/Makefile | 26 | ||||
-rwxr-xr-x | scripts/build.sh | 23 | ||||
-rwxr-xr-x | scripts/clean.sh | 6 | ||||
-rw-r--r-- | scripts/env.sh | 14 | ||||
-rw-r--r-- | test_msgnet/main.go | 195 | ||||
-rw-r--r-- | test_msgnet_tls/main.go | 221 | ||||
-rw-r--r-- | test_p2p_stress/main.go | 444 |
8 files changed, 529 insertions, 435 deletions
@@ -1,35 +1,22 @@ -# NOTE: this Makefile only serves the purpose as an example (works on my -# Linux). Your Go project uses salticidae-go should setup CGO environment -# variables properly to have a successful build. -# -# TODO: improve this Makefile - .PHONY: all clean all: build/test_msgnet build/test_p2p_stress build/test_msgnet_tls build/bench_network - -salticidae/libsalticidae.so: - cd salticidae/; cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED=ON -DSALTICIDAE_DEBUG_LOG=OFF -DSALTICIDAE_CBINDINGS=ON -DBUILD_TEST=OFF ./ - make -C salticidae/ -j4 +build/libsalticidae.a: build + scripts/build.sh build: mkdir -p build -build/test_msgnet: salticidae/libsalticidae.so test_msgnet/main.go - make -C salticidae/ - go build -o $@ github.com/Determinant/salticidae-go/test_msgnet -build/test_msgnet_tls: salticidae/libsalticidae.so test_msgnet_tls/main.go - make -C salticidae/ - go build -o $@ github.com/Determinant/salticidae-go/test_msgnet_tls -build/test_p2p_stress: salticidae/libsalticidae.so test_p2p_stress/main.go - make -C salticidae/ - go build -o $@ github.com/Determinant/salticidae-go/test_p2p_stress -build/bench_network: salticidae/libsalticidae.so bench_network/main.go - make -C salticidae/ - go build -o $@ github.com/Determinant/salticidae-go/bench_network +build/test_msgnet: build/libsalticidae.a test_msgnet/main.go + source scripts/env.sh && go build -o $@ github.com/Determinant/salticidae-go/test_msgnet +build/test_msgnet_tls: build/libsalticidae.a test_msgnet_tls/main.go + source scripts/env.sh && go build -o $@ github.com/Determinant/salticidae-go/test_msgnet_tls +build/test_p2p_stress: build/libsalticidae.a test_p2p_stress/main.go + source scripts/env.sh && go build -o $@ github.com/Determinant/salticidae-go/test_p2p_stress +build/bench_network: build/libsalticidae.a bench_network/main.go + source scripts/env.sh && go build -o $@ github.com/Determinant/salticidae-go/bench_network clean: rm -rf build/ - cd salticidae/; make clean - rm salticidae/CMakeCache.txt + scripts/clean.sh diff --git a/scripts/Makefile b/scripts/Makefile new file mode 100644 index 0000000..6cabb03 --- /dev/null +++ b/scripts/Makefile @@ -0,0 +1,26 @@ +# NOTE: do NOT use the Makefile directly, please run `./build.sh` instead + +.PHONY: all clean + +all: build/test_msgnet build/test_p2p_stress build/test_msgnet_tls build/bench_network + +build/libsalticidae.a: build + rm -f $@ + ln -sv "${GOPATH}/src/github.com/Determinant/salticidae-go/salticidae/libsalticidae.a" $@ + +build: + mkdir -p build + +build/test_msgnet: build/libsalticidae.a test_msgnet/main.go + go build -o $@ github.com/Determinant/salticidae-go/test_msgnet +build/test_msgnet_tls: build/libsalticidae.a test_msgnet_tls/main.go + go build -o $@ github.com/Determinant/salticidae-go/test_msgnet_tls +build/test_p2p_stress: build/libsalticidae.a test_p2p_stress/main.go + go build -o $@ github.com/Determinant/salticidae-go/test_p2p_stress +build/bench_network: build/libsalticidae.a bench_network/main.go + go build -o $@ github.com/Determinant/salticidae-go/bench_network + +clean: + rm -rf build/ + cd salticidae/; make clean + rm salticidae/CMakeCache.txt diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..1cf1488 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,23 @@ +#!/bin/bash -e + +prefix="$(pwd)/build" +SRC_DIR="$(dirname "${BASH_SOURCE[0]}")" + +source "${SRC_DIR}/env.sh" + +if [[ "$OSTYPE" == "linux-gnu" ]]; then + go get -d "github.com/$SALTICIDAE_ORG/salticidae-go" + cd "$SALTICIDAE_PATH" + cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX="$SALTICIDAE_PATH/build" . + make -j4 + make install + cd - +elif [[ "$OSTYPE" == "darwin"* ]]; then + brew install Determinant/salticidae/salticidae +else + echo "Your system is not supported yet." + exit 1 +fi + +rm -f "$prefix/libsalticidae.a" +ln -sv "$GOPATH/src/github.com/$SALTICIDAE_ORG/salticidae-go/salticidae/libsalticidae.a" "$prefix/libsalticidae.a" diff --git a/scripts/clean.sh b/scripts/clean.sh new file mode 100755 index 0000000..450b874 --- /dev/null +++ b/scripts/clean.sh @@ -0,0 +1,6 @@ +#!/bin/bash +SRC_DIR="$(dirname "${BASH_SOURCE[0]}")" + +source "$SRC_DIR/env.sh" +cd "$SALTICIDAE_PATH" +make clean diff --git a/scripts/env.sh b/scripts/env.sh new file mode 100644 index 0000000..318c483 --- /dev/null +++ b/scripts/env.sh @@ -0,0 +1,14 @@ +export GOPATH="$(go env GOPATH)" +export SALTICIDAE_ORG="Determinant" + +if [[ "$OSTYPE" == "linux-gnu" ]]; then + export SALTICIDAE_PATH="$GOPATH/src/github.com/$SALTICIDAE_ORG/salticidae-go/salticidae" + export CGO_CFLAGS="-I$SALTICIDAE_PATH/build/include/" + export CGO_LDFLAGS="-L$SALTICIDAE_PATH/build/lib/ -lsalticidae -luv -lssl -lcrypto -lstdc++" +elif [[ "$OSTYPE" == "darwin"* ]]; then + export CGO_CFLAGS="-I/usr/local/opt/openssl/include" + export CGO_LDFLAGS="-L/usr/local/opt/openssl/lib/ -lsalticidae -luv -lssl -lcrypto" +else + echo "Your system is not supported yet." + exit 1 +fi diff --git a/test_msgnet/main.go b/test_msgnet/main.go index e35212f..7154428 100644 --- a/test_msgnet/main.go +++ b/test_msgnet/main.go @@ -1,6 +1,5 @@ package main -// #cgo CFLAGS: -I${SRCDIR}/../salticidae/include/ // #include <stdlib.h> // #include "salticidae/network.h" // void onTerm(int sig, void *); @@ -11,147 +10,157 @@ package main import "C" import ( - "os" - "fmt" - "unsafe" - "github.com/Determinant/salticidae-go" + "fmt" + "github.com/Determinant/salticidae-go" + "os" + "unsafe" ) const ( - MSG_OPCODE_HELLO salticidae.Opcode = iota - MSG_OPCODE_ACK + MSG_OPCODE_HELLO salticidae.Opcode = iota + MSG_OPCODE_ACK ) func msgHelloSerialize(name string, text string) salticidae.Msg { - serialized := salticidae.NewDataStream(true) - serialized.PutU32(salticidae.ToLittleEndianU32(uint32(len(name)))) - serialized.PutData([]byte(name)) - serialized.PutData([]byte(text)) - return salticidae.NewMsgMovedFromByteArray( - MSG_OPCODE_HELLO, salticidae.NewByteArrayMovedFromDataStream(serialized, true), true) + serialized := salticidae.NewDataStream(true) + serialized.PutU32(salticidae.ToLittleEndianU32(uint32(len(name)))) + serialized.PutData([]byte(name)) + serialized.PutData([]byte(text)) + return salticidae.NewMsgMovedFromByteArray( + MSG_OPCODE_HELLO, salticidae.NewByteArrayMovedFromDataStream(serialized, true), true) } func msgHelloUnserialize(msg salticidae.Msg) (name string, text string) { - p := msg.GetPayloadByMove() - succ := true - length := salticidae.FromLittleEndianU32(p.GetU32(&succ)) - t := p.GetDataInPlace(int(length)); name = string(t.Get()); t.Release() - t = p.GetDataInPlace(p.Size()); text = string(t.Get()); t.Release() - return + p := msg.GetPayloadByMove() + succ := true + length := salticidae.FromLittleEndianU32(p.GetU32(&succ)) + t := p.GetDataInPlace(int(length)) + name = string(t.Get()) + t.Release() + t = p.GetDataInPlace(p.Size()) + text = string(t.Get()) + t.Release() + return } func msgAckSerialize() salticidae.Msg { - return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_ACK, salticidae.NewByteArray(true), true) + return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_ACK, salticidae.NewByteArray(true), true) } func checkError(err *salticidae.Error) { - if err.GetCode() != 0 { - fmt.Printf("error during a sync call: %s\n", salticidae.StrError(err.GetCode())) - os.Exit(1) - } + if err.GetCode() != 0 { + fmt.Printf("error during a sync call: %s\n", salticidae.StrError(err.GetCode())) + os.Exit(1) + } } type MyNet struct { - net salticidae.MsgNetwork - name string - cname *C.char + net salticidae.MsgNetwork + name string + cname *C.char } var ( - alice, bob MyNet - ec salticidae.EventContext + alice, bob MyNet + ec salticidae.EventContext ) //export onTerm func onTerm(_ C.int, _ unsafe.Pointer) { - ec.Stop() + ec.Stop() } //export onReceiveHello func onReceiveHello(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userdata unsafe.Pointer) { - msg := salticidae.MsgFromC(salticidae.CMsg(_msg)) - conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) - net := conn.GetNet() - name, text := msgHelloUnserialize(msg) - myName := C.GoString((*C.char)(userdata)) - fmt.Printf("[%s] %s says %s\n", myName, name, text) - ack := msgAckSerialize() - net.SendMsg(ack, conn) + msg := salticidae.MsgFromC(salticidae.CMsg(_msg)) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) + net := conn.GetNet() + name, text := msgHelloUnserialize(msg) + myName := C.GoString((*C.char)(userdata)) + fmt.Printf("[%s] %s says %s\n", myName, name, text) + ack := msgAckSerialize() + net.SendMsg(ack, conn) } //export onReceiveAck func onReceiveAck(_ *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userdata unsafe.Pointer) { - myName := C.GoString((*C.char)(userdata)) - fmt.Printf("[%s] the peer knows\n", myName) + myName := C.GoString((*C.char)(userdata)) + fmt.Printf("[%s] the peer knows\n", myName) } //export connHandler func connHandler(_conn *C.struct_msgnetwork_conn_t, connected C.bool, userdata unsafe.Pointer) C.bool { - conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) - net := conn.GetNet() - myName := C.GoString((*C.char)(userdata)) - n := alice - if myName == "bob" { n = bob } - if connected { - if conn.GetMode() == salticidae.CONN_MODE_ACTIVE { - fmt.Printf("[%s] connected, sending hello.\n", myName) - hello := msgHelloSerialize(myName, "Hello there!") - n.net.SendMsg(hello, conn) - } else { - fmt.Printf("[%s] accepted, waiting for greetings.\n", myName) - } - } else { - fmt.Printf("[%s] disconnected, retrying.\n", myName) - net.Connect(conn.GetAddr()) - } - return true + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) + net := conn.GetNet() + myName := C.GoString((*C.char)(userdata)) + n := alice + if myName == "bob" { + n = bob + } + if connected { + if conn.GetMode() == salticidae.CONN_MODE_ACTIVE { + fmt.Printf("[%s] connected, sending hello.\n", myName) + hello := msgHelloSerialize(myName, "Hello there!") + n.net.SendMsg(hello, conn) + } else { + fmt.Printf("[%s] accepted, waiting for greetings.\n", myName) + } + } else { + fmt.Printf("[%s] disconnected, retrying.\n", myName) + net.Connect(conn.GetAddr()) + } + return true } //export errorHandler func errorHandler(_err *C.struct_SalticidaeCError, fatal C.bool, _ unsafe.Pointer) { - err := (*salticidae.Error)(unsafe.Pointer(_err)) - s := "recoverable" - if fatal { s = "fatal" } - fmt.Printf("Captured %s error during an async call: %s\n", s, salticidae.StrError(err.GetCode())) + err := (*salticidae.Error)(unsafe.Pointer(_err)) + s := "recoverable" + if fatal { + s = "fatal" + } + fmt.Printf("Captured %s error during an async call: %s\n", s, salticidae.StrError(err.GetCode())) } func genMyNet(ec salticidae.EventContext, - name string, - myAddr salticidae.NetAddr, otherAddr salticidae.NetAddr) MyNet { - err := salticidae.NewError() - netconfig := salticidae.NewMsgNetworkConfig() - net := salticidae.NewMsgNetwork(ec, netconfig, &err); checkError(&err) - n := MyNet { net: net, name: name, cname: C.CString(name) } - cname := unsafe.Pointer(n.cname) - n.net.RegHandler(MSG_OPCODE_HELLO, salticidae.MsgNetworkMsgCallback(C.onReceiveHello), cname) - n.net.RegHandler(MSG_OPCODE_ACK, salticidae.MsgNetworkMsgCallback(C.onReceiveAck), cname) - n.net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.connHandler), cname) - n.net.RegErrorHandler(salticidae.MsgNetworkErrorCallback(C.errorHandler), cname) - - n.net.Start() - n.net.Listen(myAddr, &err); checkError(&err) - n.net.Connect(otherAddr) - return n + name string, + myAddr salticidae.NetAddr, otherAddr salticidae.NetAddr) MyNet { + err := salticidae.NewError() + netconfig := salticidae.NewMsgNetworkConfig() + net := salticidae.NewMsgNetwork(ec, netconfig, &err) + checkError(&err) + n := MyNet{net: net, name: name, cname: C.CString(name)} + cname := unsafe.Pointer(n.cname) + n.net.RegHandler(MSG_OPCODE_HELLO, salticidae.MsgNetworkMsgCallback(C.onReceiveHello), cname) + n.net.RegHandler(MSG_OPCODE_ACK, salticidae.MsgNetworkMsgCallback(C.onReceiveAck), cname) + n.net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.connHandler), cname) + n.net.RegErrorHandler(salticidae.MsgNetworkErrorCallback(C.errorHandler), cname) + + n.net.Start() + n.net.Listen(myAddr, &err) + checkError(&err) + n.net.Connect(otherAddr) + return n } func main() { - ec = salticidae.NewEventContext() - err := salticidae.NewError() + ec = salticidae.NewEventContext() + err := salticidae.NewError() - aliceAddr := salticidae.NewNetAddrFromIPPortString("127.0.0.1:12345", true, &err) - bobAddr := salticidae.NewNetAddrFromIPPortString("127.0.0.1:12346", true, &err) + aliceAddr := salticidae.NewNetAddrFromIPPortString("127.0.0.1:12345", true, &err) + bobAddr := salticidae.NewNetAddrFromIPPortString("127.0.0.1:12346", true, &err) - alice = genMyNet(ec, "alice", aliceAddr, bobAddr) - bob = genMyNet(ec, "bob", bobAddr, aliceAddr) + alice = genMyNet(ec, "alice", aliceAddr, bobAddr) + bob = genMyNet(ec, "bob", bobAddr, aliceAddr) - ev_int := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) - ev_int.Add(salticidae.SIGINT) - ev_term := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) - ev_term.Add(salticidae.SIGTERM) + ev_int := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) + ev_int.Add(salticidae.SIGINT) + ev_term := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) + ev_term.Add(salticidae.SIGTERM) - ec.Dispatch() - alice.net.Stop() - bob.net.Stop() - C.free(unsafe.Pointer(alice.cname)) - C.free(unsafe.Pointer(bob.cname)) + ec.Dispatch() + alice.net.Stop() + bob.net.Stop() + C.free(unsafe.Pointer(alice.cname)) + C.free(unsafe.Pointer(bob.cname)) } diff --git a/test_msgnet_tls/main.go b/test_msgnet_tls/main.go index 1b434b2..a53b491 100644 --- a/test_msgnet_tls/main.go +++ b/test_msgnet_tls/main.go @@ -1,6 +1,5 @@ package main -// #cgo CFLAGS: -I${SRCDIR}/../salticidae/include/ // #include <stdlib.h> // #include "salticidae/network.h" // void onTerm(int sig, void *); @@ -11,159 +10,171 @@ package main import "C" import ( - "os" - "fmt" - "unsafe" - "github.com/Determinant/salticidae-go" + "fmt" + "github.com/Determinant/salticidae-go" + "os" + "unsafe" ) const ( - MSG_OPCODE_HELLO salticidae.Opcode = iota - MSG_OPCODE_ACK + MSG_OPCODE_HELLO salticidae.Opcode = iota + MSG_OPCODE_ACK ) func msgHelloSerialize(name string, text string) salticidae.Msg { - serialized := salticidae.NewDataStream(true) - serialized.PutU32(salticidae.ToLittleEndianU32(uint32(len(name)))) - serialized.PutData([]byte(name)) - serialized.PutData([]byte(text)) - return salticidae.NewMsgMovedFromByteArray( - MSG_OPCODE_HELLO, salticidae.NewByteArrayMovedFromDataStream(serialized, true), true) + serialized := salticidae.NewDataStream(true) + serialized.PutU32(salticidae.ToLittleEndianU32(uint32(len(name)))) + serialized.PutData([]byte(name)) + serialized.PutData([]byte(text)) + return salticidae.NewMsgMovedFromByteArray( + MSG_OPCODE_HELLO, salticidae.NewByteArrayMovedFromDataStream(serialized, true), true) } func msgHelloUnserialize(msg salticidae.Msg) (name string, text string) { - p := msg.GetPayloadByMove() - succ := true - length := salticidae.FromLittleEndianU32(p.GetU32(&succ)) - t := p.GetDataInPlace(int(length)); name = string(t.Get()); t.Release() - t = p.GetDataInPlace(p.Size()); text = string(t.Get()); t.Release() - return + p := msg.GetPayloadByMove() + succ := true + length := salticidae.FromLittleEndianU32(p.GetU32(&succ)) + t := p.GetDataInPlace(int(length)) + name = string(t.Get()) + t.Release() + t = p.GetDataInPlace(p.Size()) + text = string(t.Get()) + t.Release() + return } func msgAckSerialize() salticidae.Msg { - return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_ACK, salticidae.NewByteArray(true), true) + return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_ACK, salticidae.NewByteArray(true), true) } func checkError(err *salticidae.Error) { - if err.GetCode() != 0 { - fmt.Printf("error during a sync call: %s\n", salticidae.StrError(err.GetCode())) - os.Exit(1) - } + if err.GetCode() != 0 { + fmt.Printf("error during a sync call: %s\n", salticidae.StrError(err.GetCode())) + os.Exit(1) + } } type MyNet struct { - net salticidae.MsgNetwork - name string - peerCert salticidae.UInt256 - cname *C.char + net salticidae.MsgNetwork + name string + peerCert salticidae.UInt256 + cname *C.char } var ( - alice, bob MyNet - ec salticidae.EventContext + alice, bob MyNet + ec salticidae.EventContext ) //export onTerm func onTerm(_ C.int, _ unsafe.Pointer) { - ec.Stop() + ec.Stop() } //export onReceiveHello func onReceiveHello(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userdata unsafe.Pointer) { - msg := salticidae.MsgFromC(salticidae.CMsg(_msg)) - conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) - net := conn.GetNet() - name, text := msgHelloUnserialize(msg) - myName := C.GoString((*C.char)(userdata)) - fmt.Printf("[%s] %s says %s\n", myName, name, text) - ack := msgAckSerialize() - net.SendMsg(ack, conn) + msg := salticidae.MsgFromC(salticidae.CMsg(_msg)) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) + net := conn.GetNet() + name, text := msgHelloUnserialize(msg) + myName := C.GoString((*C.char)(userdata)) + fmt.Printf("[%s] %s says %s\n", myName, name, text) + ack := msgAckSerialize() + net.SendMsg(ack, conn) } //export onReceiveAck func onReceiveAck(_ *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userdata unsafe.Pointer) { - myName := C.GoString((*C.char)(userdata)) - fmt.Printf("[%s] the peer knows\n", myName) + myName := C.GoString((*C.char)(userdata)) + fmt.Printf("[%s] the peer knows\n", myName) } //export connHandler func connHandler(_conn *C.struct_msgnetwork_conn_t, connected C.bool, userdata unsafe.Pointer) C.bool { - conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) - net := conn.GetNet() - myName := C.GoString((*C.char)(userdata)) - n := alice - if myName == "bob" { n = bob } - res := true - if connected { - certHash := conn.GetPeerCert().GetDer(true).GetHash(true) - res = certHash.IsEq(n.peerCert) - if conn.GetMode() == salticidae.CONN_MODE_ACTIVE { - fmt.Printf("[%s] connected, sending hello.\n", myName) - hello := msgHelloSerialize(myName, "Hello there!") - n.net.SendMsg(hello, conn) - } else { - status := "fail" - if res { status = "ok" } - fmt.Printf("[%s] accepted, waiting for greetings.\n" + - "The peer certificate fingerprint is %s (%s)\n", - myName, certHash.GetHex(), status) - } - } else { - fmt.Printf("[%s] disconnected, retrying.\n", myName) - net.Connect(conn.GetAddr()) - } - return C.bool(res) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) + net := conn.GetNet() + myName := C.GoString((*C.char)(userdata)) + n := alice + if myName == "bob" { + n = bob + } + res := true + if connected { + certHash := conn.GetPeerCert().GetDer(true).GetHash(true) + res = certHash.IsEq(n.peerCert) + if conn.GetMode() == salticidae.CONN_MODE_ACTIVE { + fmt.Printf("[%s] connected, sending hello.\n", myName) + hello := msgHelloSerialize(myName, "Hello there!") + n.net.SendMsg(hello, conn) + } else { + status := "fail" + if res { + status = "ok" + } + fmt.Printf("[%s] accepted, waiting for greetings.\n"+ + "The peer certificate fingerprint is %s (%s)\n", + myName, certHash.GetHex(), status) + } + } else { + fmt.Printf("[%s] disconnected, retrying.\n", myName) + net.Connect(conn.GetAddr()) + } + return C.bool(res) } //export errorHandler func errorHandler(_err *C.struct_SalticidaeCError, fatal C.bool, _ unsafe.Pointer) { - err := (*salticidae.Error)(unsafe.Pointer(_err)) - s := "recoverable" - if fatal { s = "fatal" } - fmt.Printf("Captured %s error during an async call: %s\n", s, salticidae.StrError(err.GetCode())) + err := (*salticidae.Error)(unsafe.Pointer(_err)) + s := "recoverable" + if fatal { + s = "fatal" + } + fmt.Printf("Captured %s error during an async call: %s\n", s, salticidae.StrError(err.GetCode())) } func genMyNet(ec salticidae.EventContext, - name string, peerCert string, - myAddr salticidae.NetAddr, otherAddr salticidae.NetAddr) MyNet { - err := salticidae.NewError() - netconfig := salticidae.NewMsgNetworkConfig() - netconfig.EnableTLS(true) - netconfig.TLSKeyFile(name + ".pem") - netconfig.TLSCertFile(name + ".pem") - net := salticidae.NewMsgNetwork(ec, netconfig, &err); checkError(&err) - _peerCert := salticidae.NewUInt256FromByteArray(salticidae.NewByteArrayFromHex(peerCert)) - n := MyNet { net: net, name: name, peerCert: _peerCert, cname: C.CString(name) } - cname := unsafe.Pointer(n.cname) - n.net.RegHandler(MSG_OPCODE_HELLO, salticidae.MsgNetworkMsgCallback(C.onReceiveHello), cname) - n.net.RegHandler(MSG_OPCODE_ACK, salticidae.MsgNetworkMsgCallback(C.onReceiveAck), cname) - n.net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.connHandler), cname) - n.net.RegErrorHandler(salticidae.MsgNetworkErrorCallback(C.errorHandler), cname) - - n.net.Start() - n.net.Listen(myAddr, &err); checkError(&err) - n.net.Connect(otherAddr) - return n + name string, peerCert string, + myAddr salticidae.NetAddr, otherAddr salticidae.NetAddr) MyNet { + err := salticidae.NewError() + netconfig := salticidae.NewMsgNetworkConfig() + netconfig.EnableTLS(true) + netconfig.TLSKeyFile(name + ".pem") + netconfig.TLSCertFile(name + ".pem") + net := salticidae.NewMsgNetwork(ec, netconfig, &err) + checkError(&err) + _peerCert := salticidae.NewUInt256FromByteArray(salticidae.NewByteArrayFromHex(peerCert)) + n := MyNet{net: net, name: name, peerCert: _peerCert, cname: C.CString(name)} + cname := unsafe.Pointer(n.cname) + n.net.RegHandler(MSG_OPCODE_HELLO, salticidae.MsgNetworkMsgCallback(C.onReceiveHello), cname) + n.net.RegHandler(MSG_OPCODE_ACK, salticidae.MsgNetworkMsgCallback(C.onReceiveAck), cname) + n.net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.connHandler), cname) + n.net.RegErrorHandler(salticidae.MsgNetworkErrorCallback(C.errorHandler), cname) + + n.net.Start() + n.net.Listen(myAddr, &err) + checkError(&err) + n.net.Connect(otherAddr) + return n } func main() { - ec = salticidae.NewEventContext() - err := salticidae.NewError() + ec = salticidae.NewEventContext() + err := salticidae.NewError() - aliceAddr := salticidae.NewNetAddrFromIPPortString("127.0.0.1:12345", true, &err) - bobAddr := salticidae.NewNetAddrFromIPPortString("127.0.0.1:12346", true, &err) + aliceAddr := salticidae.NewNetAddrFromIPPortString("127.0.0.1:12345", true, &err) + bobAddr := salticidae.NewNetAddrFromIPPortString("127.0.0.1:12346", true, &err) - alice = genMyNet(ec, "alice", "ed5a9a8c7429dcb235a88244bc69d43d16b35008ce49736b27aaa3042a674043", aliceAddr, bobAddr) - bob = genMyNet(ec, "bob", "ef3bea4e72f4d0e85da7643545312e2ff6dded5e176560bdffb1e53b1cef4896", bobAddr, aliceAddr) + alice = genMyNet(ec, "alice", "ed5a9a8c7429dcb235a88244bc69d43d16b35008ce49736b27aaa3042a674043", aliceAddr, bobAddr) + bob = genMyNet(ec, "bob", "ef3bea4e72f4d0e85da7643545312e2ff6dded5e176560bdffb1e53b1cef4896", bobAddr, aliceAddr) - ev_int := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) - ev_int.Add(salticidae.SIGINT) - ev_term := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) - ev_term.Add(salticidae.SIGTERM) + ev_int := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) + ev_int.Add(salticidae.SIGINT) + ev_term := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) + ev_term.Add(salticidae.SIGTERM) - ec.Dispatch() - alice.net.Stop() - bob.net.Stop() - C.free(unsafe.Pointer(alice.cname)) - C.free(unsafe.Pointer(bob.cname)) + ec.Dispatch() + alice.net.Stop() + bob.net.Stop() + C.free(unsafe.Pointer(alice.cname)) + C.free(unsafe.Pointer(bob.cname)) } diff --git a/test_p2p_stress/main.go b/test_p2p_stress/main.go index 103ec4b..095dc56 100644 --- a/test_p2p_stress/main.go +++ b/test_p2p_stress/main.go @@ -1,7 +1,5 @@ package main -// #cgo CFLAGS: -I${SRCDIR}/../salticidae/include/ -// #cgo LDFLAGS: ${SRCDIR}/../salticidae/libsalticidae.so -Wl,-rpath=${SRCDIR}/salticidae/ // #include <stdlib.h> // #include <stdint.h> // #include <arpa/inet.h> @@ -27,114 +25,121 @@ package main import "C" import ( - "github.com/Determinant/salticidae-go" - "math/rand" - "os" - "fmt" - "sync" - "unsafe" - "strconv" + "fmt" + "github.com/Determinant/salticidae-go" + "math/rand" + "os" + "strconv" + "sync" + "unsafe" ) const ( - MSG_OPCODE_RAND salticidae.Opcode = iota - MSG_OPCODE_ACK + MSG_OPCODE_RAND salticidae.Opcode = iota + MSG_OPCODE_ACK ) func msgRandSerialize(view uint32, size int) (salticidae.Msg, salticidae.UInt256) { - serialized := salticidae.NewDataStream(false); defer serialized.Free() - serialized.PutU32(salticidae.ToLittleEndianU32(view)) - buffer := make([]byte, size) - _, err := rand.Read(buffer) - if err != nil { - panic("rand source failed") - } - serialized.PutData(buffer) - ba := salticidae.NewByteArrayFromBytes(buffer, false); defer ba.Free() - payload := salticidae.NewByteArrayMovedFromDataStream(serialized, false); defer payload.Free() - return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_RAND, payload, false), ba.GetHash(true) + serialized := salticidae.NewDataStream(false) + defer serialized.Free() + serialized.PutU32(salticidae.ToLittleEndianU32(view)) + buffer := make([]byte, size) + _, err := rand.Read(buffer) + if err != nil { + panic("rand source failed") + } + serialized.PutData(buffer) + ba := salticidae.NewByteArrayFromBytes(buffer, false) + defer ba.Free() + payload := salticidae.NewByteArrayMovedFromDataStream(serialized, false) + defer payload.Free() + return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_RAND, payload, false), ba.GetHash(true) } func msgRandUnserialize(msg salticidae.Msg) (view uint32, hash salticidae.UInt256) { - payload := msg.GetPayloadByMove() - succ := true - view = salticidae.FromLittleEndianU32(payload.GetU32(&succ)) - ba := salticidae.NewByteArrayCopiedFromDataStream(payload, false); defer ba.Free() - hash = ba.GetHash(false) - return + payload := msg.GetPayloadByMove() + succ := true + view = salticidae.FromLittleEndianU32(payload.GetU32(&succ)) + ba := salticidae.NewByteArrayCopiedFromDataStream(payload, false) + defer ba.Free() + hash = ba.GetHash(false) + return } func msgAckSerialize(view uint32, hash salticidae.UInt256) salticidae.Msg { - serialized := salticidae.NewDataStream(false); defer serialized.Free() - serialized.PutU32(salticidae.ToLittleEndianU32(view)) - hash.Serialize(serialized) - payload := salticidae.NewByteArrayMovedFromDataStream(serialized, false); defer payload.Free() - return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_ACK, payload, false) + serialized := salticidae.NewDataStream(false) + defer serialized.Free() + serialized.PutU32(salticidae.ToLittleEndianU32(view)) + hash.Serialize(serialized) + payload := salticidae.NewByteArrayMovedFromDataStream(serialized, false) + defer payload.Free() + return salticidae.NewMsgMovedFromByteArray(MSG_OPCODE_ACK, payload, false) } func msgAckUnserialize(msg salticidae.Msg) (view uint32, hash salticidae.UInt256) { - payload := msg.GetPayloadByMove() - hash = salticidae.NewUInt256(false) - succ := true - view = salticidae.FromLittleEndianU32(payload.GetU32(&succ)) - hash.Unserialize(payload) - return + payload := msg.GetPayloadByMove() + hash = salticidae.NewUInt256(false) + succ := true + view = salticidae.FromLittleEndianU32(payload.GetU32(&succ)) + hash.Unserialize(payload) + return } func checkError(err *salticidae.Error) { - if err.GetCode() != 0 { - fmt.Printf("error during a sync call: %s\n", salticidae.StrError(err.GetCode())) - os.Exit(1) - } + if err.GetCode() != 0 { + fmt.Printf("error during a sync call: %s\n", salticidae.StrError(err.GetCode())) + os.Exit(1) + } } type TestContext struct { - timer salticidae.TimerEvent - timer_ctx *C.struct_timeout_callback_context_t - state int - view uint32 - hash salticidae.UInt256 - ncompleted int + timer salticidae.TimerEvent + timer_ctx *C.struct_timeout_callback_context_t + state int + view uint32 + hash salticidae.UInt256 + ncompleted int } type AppContext struct { - addr salticidae.NetAddr - ec salticidae.EventContext - net salticidae.PeerNetwork - tcall salticidae.ThreadCall - tc map[uint64] *TestContext + addr salticidae.NetAddr + ec salticidae.EventContext + net salticidae.PeerNetwork + tcall salticidae.ThreadCall + tc map[uint64]*TestContext } func (self AppContext) Free() { - for _, tc := range self.tc { - if tc.timer != nil { - C.free(unsafe.Pointer(tc.timer_ctx)) - } - } + for _, tc := range self.tc { + if tc.timer != nil { + C.free(unsafe.Pointer(tc.timer_ctx)) + } + } } func NewTestContext() TestContext { - return TestContext { view: 0, ncompleted: 0 } + return TestContext{view: 0, ncompleted: 0} } func addr2id(addr salticidae.NetAddr) uint64 { - return uint64(addr.GetIP()) | (uint64(addr.GetPort()) << 32) + return uint64(addr.GetIP()) | (uint64(addr.GetPort()) << 32) } func (self AppContext) getTC(addr_id uint64) (_tc *TestContext) { - if tc, ok := self.tc[addr_id]; ok { - _tc = tc - } else { - _tc = new(TestContext) - self.tc[addr_id] = _tc - } - return + if tc, ok := self.tc[addr_id]; ok { + _tc = tc + } else { + _tc = new(TestContext) + self.tc[addr_id] = _tc + } + return } func sendRand(size int, app *AppContext, conn salticidae.MsgNetworkConn, tc *TestContext) { - msg, hash := msgRandSerialize(tc.view, size); defer msg.Free() - tc.hash = hash - app.net.AsMsgNetwork().SendMsg(msg, conn) + msg, hash := msgRandSerialize(tc.view, size) + defer msg.Free() + tc.hash = hash + app.net.AsMsgNetwork().SendMsg(msg, conn) } var apps []AppContext @@ -145,180 +150,193 @@ var ids []*C.int //export onTimeout func onTimeout(_ *C.timerev_t, userdata unsafe.Pointer) { - ctx := (*C.struct_timeout_callback_context_t)(userdata) - app := &apps[int(ctx.app_id)] - tc := app.getTC(uint64(ctx.addr_id)) - tc.ncompleted++ - app.net.AsMsgNetwork().Terminate( - salticidae.MsgNetworkConnFromC( - salticidae.CMsgNetworkConn(ctx.conn))) - var s string - for addr_id, v := range app.tc { - s += fmt.Sprintf(" %d(%d)", C.ntohs(C.ushort(addr_id >> 32)), v.ncompleted) - } - fmt.Printf("INFO: %d completed:%s\n", C.ntohs(C.ushort(app.addr.GetPort())), s) + ctx := (*C.struct_timeout_callback_context_t)(userdata) + app := &apps[int(ctx.app_id)] + tc := app.getTC(uint64(ctx.addr_id)) + tc.ncompleted++ + app.net.AsMsgNetwork().Terminate( + salticidae.MsgNetworkConnFromC( + salticidae.CMsgNetworkConn(ctx.conn))) + var s string + for addr_id, v := range app.tc { + s += fmt.Sprintf(" %d(%d)", C.ntohs(C.ushort(addr_id>>32)), v.ncompleted) + } + fmt.Printf("INFO: %d completed:%s\n", C.ntohs(C.ushort(app.addr.GetPort())), s) } //export onReceiveRand func onReceiveRand(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) { - msg := salticidae.MsgFromC(salticidae.CMsg(_msg)) - conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) - net := conn.GetNet() - view, hash := msgRandUnserialize(msg); defer hash.Free() - ack := msgAckSerialize(view, hash); defer ack.Free() - net.SendMsg(ack, conn) + msg := salticidae.MsgFromC(salticidae.CMsg(_msg)) + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) + net := conn.GetNet() + view, hash := msgRandUnserialize(msg) + defer hash.Free() + ack := msgAckSerialize(view, hash) + defer ack.Free() + net.SendMsg(ack, conn) } //export onReceiveAck func onReceiveAck(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, userdata unsafe.Pointer) { - view, hash := msgAckUnserialize(salticidae.MsgFromC(salticidae.CMsg(_msg))); defer hash.Free() - id := int(*(*C.int)(userdata)) - app := &apps[id] - conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) - pconn := salticidae.NewPeerNetworkConnFromMsgNetworkConnUnsafe(conn, false); defer pconn.Free() - addr := pconn.GetPeerAddr(false); defer addr.Free() - if addr.IsNull() { return } - addrID := addr2id(addr) - tc := app.getTC(addrID) + view, hash := msgAckUnserialize(salticidae.MsgFromC(salticidae.CMsg(_msg))) + defer hash.Free() + id := int(*(*C.int)(userdata)) + app := &apps[id] + conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn)) + pconn := salticidae.NewPeerNetworkConnFromMsgNetworkConnUnsafe(conn, false) + defer pconn.Free() + addr := pconn.GetPeerAddr(false) + defer addr.Free() + if addr.IsNull() { + return + } + addrID := addr2id(addr) + tc := app.getTC(addrID) - if view != tc.view { - fmt.Printf("dropping stale MsgAck\n") - return - } + if view != tc.view { + fmt.Printf("dropping stale MsgAck\n") + return + } - if !hash.IsEq(tc.hash) { - panic("corrupted I/O!") - } + if !hash.IsEq(tc.hash) { + panic("corrupted I/O!") + } - if tc.state == segBuffSize * 2 { - sendRand(tc.state, app, conn, tc) - tc.state = -1 - ctx := C.timeout_callback_context_new() - ctx.app_id = C.int(id) - ctx.addr_id = C.uint64_t(addrID) - ctx.conn = C.msgnetwork_conn_copy(_conn) - if tc.timer != nil { - C.msgnetwork_conn_free(tc.timer_ctx.conn) - C.free(unsafe.Pointer(tc.timer_ctx)) - tc.timer.Del() - } - tc.timer = salticidae.NewTimerEvent(app.ec, salticidae.TimerEventCallback(C.onTimeout), unsafe.Pointer(ctx)) - tc.timer_ctx = ctx - t := rand.Float64() * 10 - tc.timer.Add(t) - fmt.Printf("rand-bomboard phase, ending in %.2f secs\n", t) - } else if tc.state == -1 { - sendRand(rand.Int() % (segBuffSize * 10), app, conn, tc) - } else { - tc.state++ - sendRand(tc.state, app, conn, tc) - } + if tc.state == segBuffSize*2 { + sendRand(tc.state, app, conn, tc) + tc.state = -1 + ctx := C.timeout_callback_context_new() + ctx.app_id = C.int(id) + ctx.addr_id = C.uint64_t(addrID) + ctx.conn = C.msgnetwork_conn_copy(_conn) + if tc.timer != nil { + C.msgnetwork_conn_free(tc.timer_ctx.conn) + C.free(unsafe.Pointer(tc.timer_ctx)) + tc.timer.Del() + } + tc.timer = salticidae.NewTimerEvent(app.ec, salticidae.TimerEventCallback(C.onTimeout), unsafe.Pointer(ctx)) + tc.timer_ctx = ctx + t := rand.Float64() * 10 + tc.timer.Add(t) + fmt.Printf("rand-bomboard phase, ending in %.2f secs\n", t) + } else if tc.state == -1 { + sendRand(rand.Int()%(segBuffSize*10), app, conn, tc) + } else { + tc.state++ + sendRand(tc.state, app, conn, tc) + } } //export peerHandler func peerHandler(_conn *C.struct_peernetwork_conn_t, connected C.bool, userdata unsafe.Pointer) { - if connected { - pconn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn)) - conn := salticidae.NewMsgNetworkConnFromPeerNetworkConn(pconn, false); defer conn.Free() - id := int(*(*C.int)(userdata)) - app := &apps[id] - addr := pconn.GetPeerAddr(false); defer addr.Free() - tc := app.getTC(addr2id(addr)) - tc.state = 1 - tc.view++ - sendRand(tc.state, app, conn, tc) - } + if connected { + pconn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn)) + conn := salticidae.NewMsgNetworkConnFromPeerNetworkConn(pconn, false) + defer conn.Free() + id := int(*(*C.int)(userdata)) + app := &apps[id] + addr := pconn.GetPeerAddr(false) + defer addr.Free() + tc := app.getTC(addr2id(addr)) + tc.state = 1 + tc.view++ + sendRand(tc.state, app, conn, tc) + } } //export errorHandler func errorHandler(_err *C.struct_SalticidaeCError, fatal C.bool, asyncID C.int32_t, _ unsafe.Pointer) { - err := (*salticidae.Error)(unsafe.Pointer(_err)) - s := "recoverable" - if fatal { s = "fatal" } - fmt.Printf("Captured %s error during an async call %d: %s\n", s, asyncID, salticidae.StrError(err.GetCode())) + err := (*salticidae.Error)(unsafe.Pointer(_err)) + s := "recoverable" + if fatal { + s = "fatal" + } + fmt.Printf("Captured %s error during an async call %d: %s\n", s, asyncID, salticidae.StrError(err.GetCode())) } //export onStopLoop func onStopLoop(_ *C.threadcall_handle_t, userdata unsafe.Pointer) { - id := int(*(*C.int)(userdata)) - ec := apps[id].ec - ec.Stop() + id := int(*(*C.int)(userdata)) + ec := apps[id].ec + ec.Stop() } //export onTerm func onTerm(_ C.int, _ unsafe.Pointer) { - for i, _ := range apps { - a := &apps[i] - a.tcall.AsyncCall( - salticidae.ThreadCallCallback(C.onStopLoop), - unsafe.Pointer(ids[i])) - } - threads.Wait() - ec.Stop() + for i, _ := range apps { + a := &apps[i] + a.tcall.AsyncCall( + salticidae.ThreadCallCallback(C.onStopLoop), + unsafe.Pointer(ids[i])) + } + threads.Wait() + ec.Stop() } func main() { - ec = salticidae.NewEventContext() - err := salticidae.NewError() + ec = salticidae.NewEventContext() + err := salticidae.NewError() - var addrs []salticidae.NetAddr - for i := 0; i < 5; i++ { - addrs = append(addrs, - salticidae.NewNetAddrFromIPPortString("127.0.0.1:" + strconv.Itoa(12345 + i), true, &err)) - } - netconfig := salticidae.NewPeerNetworkConfig() - nc := netconfig.AsMsgNetworkConfig() - nc.SegBuffSize(segBuffSize) - nc.NWorker(2) - netconfig.ConnTimeout(5) - netconfig.PingPeriod(2) - apps = make([]AppContext, len(addrs)) - ids = make([](*C.int), len(addrs)) - for i, addr := range addrs { - ec := salticidae.NewEventContext() - net := salticidae.NewPeerNetwork(ec, netconfig, &err); checkError(&err) - apps[i] = AppContext { - addr: addr, - ec: ec, - net: net, - tcall: salticidae.NewThreadCall(ec), - tc: make(map[uint64] *TestContext), - } - ids[i] = (*C.int)(C.malloc(C.sizeof_int)) - *ids[i] = C.int(i) - _i := unsafe.Pointer(ids[i]) - mnet := net.AsMsgNetwork() - mnet.RegHandler(MSG_OPCODE_RAND, salticidae.MsgNetworkMsgCallback(C.onReceiveRand), _i) - mnet.RegHandler(MSG_OPCODE_ACK, salticidae.MsgNetworkMsgCallback(C.onReceiveAck), _i) - net.RegPeerHandler(salticidae.PeerNetworkPeerCallback(C.peerHandler), _i) - mnet.RegErrorHandler(salticidae.MsgNetworkErrorCallback(C.errorHandler), _i) - mnet.Start() - } + var addrs []salticidae.NetAddr + for i := 0; i < 5; i++ { + addrs = append(addrs, + salticidae.NewNetAddrFromIPPortString("127.0.0.1:"+strconv.Itoa(12345+i), true, &err)) + } + netconfig := salticidae.NewPeerNetworkConfig() + nc := netconfig.AsMsgNetworkConfig() + nc.SegBuffSize(segBuffSize) + nc.NWorker(2) + netconfig.ConnTimeout(5) + netconfig.PingPeriod(2) + apps = make([]AppContext, len(addrs)) + ids = make([](*C.int), len(addrs)) + for i, addr := range addrs { + ec := salticidae.NewEventContext() + net := salticidae.NewPeerNetwork(ec, netconfig, &err) + checkError(&err) + apps[i] = AppContext{ + addr: addr, + ec: ec, + net: net, + tcall: salticidae.NewThreadCall(ec), + tc: make(map[uint64]*TestContext), + } + ids[i] = (*C.int)(C.malloc(C.sizeof_int)) + *ids[i] = C.int(i) + _i := unsafe.Pointer(ids[i]) + mnet := net.AsMsgNetwork() + mnet.RegHandler(MSG_OPCODE_RAND, salticidae.MsgNetworkMsgCallback(C.onReceiveRand), _i) + mnet.RegHandler(MSG_OPCODE_ACK, salticidae.MsgNetworkMsgCallback(C.onReceiveAck), _i) + net.RegPeerHandler(salticidae.PeerNetworkPeerCallback(C.peerHandler), _i) + mnet.RegErrorHandler(salticidae.MsgNetworkErrorCallback(C.errorHandler), _i) + mnet.Start() + } - threads.Add(len(apps)) - for i, _ := range apps { - app_id := i - go func() { - err := salticidae.NewError() - a := &apps[app_id] - a.net.Listen(a.addr, &err); checkError(&err) - for _, addr := range addrs { - if !addr.IsEq(a.addr) { - a.net.AddPeer(addr) - } - } - a.ec.Dispatch() - a.net.AsMsgNetwork().Stop() - a.Free() - C.free(unsafe.Pointer(ids[app_id])) - threads.Done() - }() - } + threads.Add(len(apps)) + for i, _ := range apps { + app_id := i + go func() { + err := salticidae.NewError() + a := &apps[app_id] + a.net.Listen(a.addr, &err) + checkError(&err) + for _, addr := range addrs { + if !addr.IsEq(a.addr) { + a.net.AddPeer(addr) + } + } + a.ec.Dispatch() + a.net.AsMsgNetwork().Stop() + a.Free() + C.free(unsafe.Pointer(ids[app_id])) + threads.Done() + }() + } - ev_int := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) - ev_int.Add(salticidae.SIGINT) - ev_term := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) - ev_term.Add(salticidae.SIGTERM) + ev_int := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) + ev_int.Add(salticidae.SIGINT) + ev_term := salticidae.NewSigEvent(ec, salticidae.SigEventCallback(C.onTerm), nil) + ev_term.Add(salticidae.SIGTERM) - ec.Dispatch() + ec.Dispatch() } |