@CoRfr outside the sandbox is the same behavior.
Last time I’ve tried CoreOS it was a pain to debug exactly for the reason that you couldn’t really use the normal linux debugging tools. So careful what you wish for
The fact that the directory service does not respond means that it is either dropping the message silently or that it is not permitted to send a response and won’t even send an error. I’ll try to find the source for the directory service but does this ring any bell? Also, is there a quick way for me to recompile the directory service so that I can add some debug messages or do I have to rebuild legato for this?
@CoRfr found it. The binding
definition was wrong. Must be printServer.printer
and not printerService.printer
. Now I can implement the rest of the protocol …
This is more idiomatic Go using the net
package and that works now as well:
package main
import (
"bytes"
"encoding/binary"
"log"
"net"
)
const (
ProtocolID = "e2533dc76a5bf9ba6b2d3e74d8f95bd6" // /legato/apps/sample/helloIpc/printer.api
ServiceInstanceName = "printer"
MaxMsgSize = 112
msgID_printer_Print = 0
sock = "/tmp/legato/serviceDirectoryClient"
)
type OpenMsg struct {
MaxSize uint32
ProtoID [128]byte
IntfName [128]byte
Wait bool
_ [3]byte // padding
}
func NewOpenMsg() *OpenMsg {
openMsg := &OpenMsg{
MaxSize: MaxMsgSize + 4,
Wait: true,
}
copy(openMsg.ProtoID[:], []byte(ProtocolID))
copy(openMsg.IntfName[:], []byte(ServiceInstanceName))
return openMsg
}
func main() {
conn, err := net.Dial("unixpacket", sock)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
msg := NewOpenMsg()
var b bytes.Buffer
if err := binary.Write(&b, binary.LittleEndian, msg); err != nil {
log.Fatal(err)
}
n, err := conn.Write(b.Bytes())
if err != nil {
log.Fatal(err)
}
buf := make([]byte, 4)
n, err = conn.Read(buf)
if err != nil {
log.Fatal(err)
}
buf = buf[:n]
log.Printf("resp: buf: %#v", buf)
log.Print("Done")
}
CoRfr
June 19, 2018, 9:39pm
24
Oh that is really nice!
I guess that file could be generated by ifgen
with the appropriate values regarding ProtocolID
and ServiceInstanceName
, but that opens things a bit.
One big thing as well is the rest of the IPC, as there needs to be a packing/unpacking of things that goes on the wire.
It might be possible to reuse quite a bit of what other languages are doing like the python implementation is doing, cf https://github.com/legatoproject/legato-af/blob/master/framework/tools/ifgen/langPython/__init__.py for instance.
Success. This works:
package main
import (
"bytes"
"encoding/binary"
"log"
"net"
"unsafe"
)
const (
ProtocolID = "e2533dc76a5bf9ba6b2d3e74d8f95bd6" // /legato/apps/sample/helloIpc/printer.api
ServiceInstanceName = "printer"
MaxMsgSize = 112
msgID_printer_Print = 0
sock = "/tmp/legato/serviceDirectoryClient"
)
type OpenMsg struct {
MaxSize uint32
ProtoID [128]byte
IntfName [128]byte
Wait bool
_ [3]byte // padding
}
func NewOpenMsg() *OpenMsg {
openMsg := &OpenMsg{
MaxSize: MaxMsgSize + 4,
Wait: true,
}
copy(openMsg.ProtoID[:], []byte(ProtocolID))
copy(openMsg.IntfName[:], []byte(ServiceInstanceName))
return openMsg
}
func main() {
// log.Print("Starting socket")
// time.Sleep(10 * time.Second)
conn, err := net.Dial("unixpacket", sock)
if err != nil {
log.Fatal(err)
}
defer conn.Close()
if err := SendMsg(conn, NewOpenMsg()); err != nil {
log.Fatal(err)
}
var res int32
if err := ReadMsg(conn, &res); err != nil {
log.Fatal(err)
}
if res != 0 {
log.Fatal("got %d want 0", res)
}
log.Print("Session Created")
type PrinterMessage struct {
TxID uint32 // pointer size 32 or 64 bit I guess
MsgID uint32
Len uint32
Payload [MaxMsgSize - 4]byte
}
data := []byte("Hello from Go")
msg := &PrinterMessage{
TxID: 0xabbaabba,
MsgID: msgID_printer_Print,
Len: uint32(len(data)),
}
copy(msg.Payload[:], data)
if err := SendMsg(conn, msg); err != nil {
log.Fatal(err)
}
log.Print("message sent")
log.Print("Done")
}
func SendMsg(conn net.Conn, v interface{}) error {
var b bytes.Buffer
if err := binary.Write(&b, binary.LittleEndian, v); err != nil {
return err
}
_, err := conn.Write(b.Bytes())
return err
}
func ReadMsg(conn net.Conn, v interface{}) error {
b := make([]byte, unsafe.Sizeof(v))
n, err := conn.Read(b)
if err != nil {
return err
}
b = b[:n]
return binary.Read(bytes.NewReader(b), binary.LittleEndian, v)
}
Now for cleaning up the code and message multiplexing…