-
Notifications
You must be signed in to change notification settings - Fork 207
/
agcosmosdaemon.go
110 lines (97 loc) · 2.72 KB
/
agcosmosdaemon.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main
// /* These comments before the import "C" are included in the C output. */
// #include <stdlib.h>
// typedef const char* Body;
// typedef int (*sendFunc)(int, int, Body);
// inline int invokeSendFunc(sendFunc send, int port, int reply, Body str) {
// return send(port, reply, str);
// }
import "C"
import (
"errors"
"fmt"
"os"
"github.com/Agoric/cosmic-swingset/lib/daemon"
swingset "github.com/Agoric/cosmic-swingset/x/swingset"
)
type goReturn = struct {
str string
err error
}
const SwingSetPort = 123
var replies = map[int]chan goReturn{}
var lastReply = 0
//export RunAG_COSMOS
func RunAG_COSMOS(nodePort C.int, toNode C.sendFunc, cosmosArgs []*C.char) C.int {
// FIXME: Decouple the sending logic from the Cosmos app.
sendToNode := func(needReply bool, str string) (string, error) {
var rPort int
if needReply {
lastReply++
rPort = lastReply
replies[rPort] = make(chan goReturn)
}
// Send the message
C.invokeSendFunc(toNode, nodePort, C.int(rPort), C.CString(str))
if !needReply {
// Return immediately
// fmt.Fprintln(os.Stderr, "Don't wait")
return "<no-reply-requested>", nil
}
// Block the sending goroutine while we wait for the reply
// fmt.Fprintln(os.Stderr, "Waiting for", rPort)
ret := <-replies[rPort]
delete(replies, rPort)
// fmt.Fprintln(os.Stderr, "Woken, got", ret)
return ret.str, ret.err
}
args := make([]string, len(cosmosArgs))
for i, s := range cosmosArgs {
args[i] = C.GoString(s)
}
// fmt.Fprintln(os.Stderr, "Starting Cosmos", args)
os.Args = args
go func() {
// We run in the background, but exit when the job is over.
// swingset.SendToNode("hello from Initial Go!")
daemon.RunWithController(sendToNode)
// fmt.Fprintln(os.Stderr, "Shutting down Cosmos")
os.Exit(0)
}()
// fmt.Fprintln(os.Stderr, "Done starting Cosmos")
return SwingSetPort
}
//export ReplyToGo
func ReplyToGo(replyPort C.int, isError C.int, str C.Body) C.int {
goStr := C.GoString(str)
// fmt.Fprintln(os.Stderr, "Reply to Go", goStr)
returnCh := replies[int(replyPort)]
if returnCh == nil {
// Unexpected reply.
// This is okay, since the caller decides whether or
// not she wants to listen for replies.
return C.int(0)
}
// Wake up the waiting goroutine
ret := goReturn{}
if int(isError) == 0 {
ret.str = goStr
} else {
ret.err = errors.New(goStr)
}
returnCh <- ret
return C.int(0)
}
//export SendToGo
func SendToGo(port C.int, str C.Body) C.Body {
goStr := C.GoString(str)
// fmt.Fprintln(os.Stderr, "Send to Go", goStr)
outstr, err := swingset.ReceiveFromNode(int(port), goStr)
if err != nil {
fmt.Fprintln(os.Stderr, "Cannot receive from node", err)
return C.CString("")
}
return C.CString(outstr)
}
// Do nothing in main.
func main() {}