diff --git a/.gitignore b/.gitignore
index 6ba4ef0..dd73b4c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,3 +17,5 @@
/beeper-imessage
/start
/.android-ipc-bin
+/imgo.h
+/imgo.so
diff --git a/android-ipc b/android-ffi
similarity index 60%
rename from android-ipc
rename to android-ffi
index e4800f0..3dc5816 100755
--- a/android-ipc
+++ b/android-ffi
@@ -3,6 +3,5 @@ set -e
repo_dir=$(dirname $(realpath $0))
pushd $repo_dir > /dev/null
LDFLAGS="-X main.Tag=$(git describe --exact-match --tags 2>/dev/null) -X main.Commit=$(git rev-parse HEAD) -X 'main.BuildTime=$(date '+%b %_d %Y, %H:%M:%S')'"
-go build -ldflags "$LDFLAGS" -o .android-ipc-bin ./imessage/ipc/
+go build -ldflags "$LDFLAGS" -buildmode=c-shared -o imgo.so ./imessage/ffi/
popd > /dev/null
-rlwrap -H "$HOME/.android-ipc_history" $repo_dir/.android-ipc-bin 2> >(zeroparse >&2) | (trap '' INT; jq -c)
diff --git a/android/imessage.sh b/android/imessage.sh
index 2004228..ab308bb 100755
--- a/android/imessage.sh
+++ b/android/imessage.sh
@@ -40,7 +40,7 @@ build_imessage() {
(set -x; CGO_LDFLAGS="-lm -llog" CGO_ENABLED=1 GOOS=android GOARCH=$GOARCH GOARM=$GOARM \
CC="$NDK_ROOT/toolchains/llvm/prebuilt/$NDK_ARCH/bin/$NDK_TARGET$ANDROID_API-clang" \
- go build -ldflags "$LDFLAGS" -o "$LIB_JNI"/libima.so ./imessage/ipc)
+ go build -ldflags "$LDFLAGS" -o "$LIB_JNI"/libima.so ./imessage/ffi)
}
build_imessage armeabi-v7a armv7a-linux-androideabi arm 7
diff --git a/imessage/ipc/bridgeinfo.go b/imessage/ffi/bridgeinfo.go
similarity index 100%
rename from imessage/ipc/bridgeinfo.go
rename to imessage/ffi/bridgeinfo.go
diff --git a/imessage/ipc/commands.go b/imessage/ffi/commands.go
similarity index 100%
rename from imessage/ipc/commands.go
rename to imessage/ffi/commands.go
diff --git a/imessage/ipc/events.go b/imessage/ffi/events.go
similarity index 99%
rename from imessage/ipc/events.go
rename to imessage/ffi/events.go
index 378defe..5146740 100644
--- a/imessage/ipc/events.go
+++ b/imessage/ffi/events.go
@@ -824,6 +824,10 @@ func handleDelivered(status *direct.MessageDelivered) {
}
}
+type ReqStarted struct {
+ LoggedIn bool `json:"logged_in"`
+}
+
func handleEvent(evt any) {
switch typedEvt := evt.(type) {
case *imessage.Message:
diff --git a/imessage/ipc/filetransfer.go b/imessage/ffi/filetransfer.go
similarity index 100%
rename from imessage/ipc/filetransfer.go
rename to imessage/ffi/filetransfer.go
diff --git a/imessage/ipc/global.go b/imessage/ffi/global.go
similarity index 99%
rename from imessage/ipc/global.go
rename to imessage/ffi/global.go
index 652d33d..89bea89 100644
--- a/imessage/ipc/global.go
+++ b/imessage/ffi/global.go
@@ -43,7 +43,7 @@ import (
"github.com/beeper/imessage/imessage/direct/ids"
"github.com/beeper/imessage/imessage/direct/nacserv"
"github.com/beeper/imessage/imessage/direct/util/httputil"
- "github.com/beeper/imessage/imessage/ipc/imux"
+ "github.com/beeper/imessage/imessage/ffi/imux"
"github.com/beeper/imessage/ipc"
"github.com/beeper/imessage/msgconv"
)
diff --git a/imessage/ipc/imux/imux.go b/imessage/ffi/imux/imux.go
similarity index 100%
rename from imessage/ipc/imux/imux.go
rename to imessage/ffi/imux/imux.go
diff --git a/imessage/ipc/main.go b/imessage/ffi/main.go
similarity index 98%
rename from imessage/ipc/main.go
rename to imessage/ffi/main.go
index 8956358..1abcb33 100644
--- a/imessage/ipc/main.go
+++ b/imessage/ffi/main.go
@@ -16,6 +16,7 @@
package main
+import "C"
import (
"context"
_ "embed"
@@ -89,8 +90,11 @@ func analyticsTrackOverIPC(event string, properties map[string]any) error {
})
}
-func main() {
- writer := ipc.NewLockedWriter(os.Stdout)
+func main() {}
+
+//export start
+func start() {
+ writer := ipc.NewLockedWriter(&FFIStdout)
zeroconfig.RegisterWriter(writerTypeStdoutIPC, func(config *zeroconfig.WriterConfig) (io.Writer, error) {
return writer, nil
})
@@ -121,7 +125,7 @@ func main() {
}
ipcLog := log.With().Str("component", "ipc").Logger()
- global.IPC = ipc.NewProcessor(writer, os.Stdin, &ipcLog)
+ global.IPC = ipc.NewProcessor(writer, FFIStdinReader, &ipcLog)
global.IPC.SetHandler(CmdLogin, ipc.TypedHandler(fnLogin))
global.IPC.SetHandler(CmdMessage, ipc.TypedHandler(fnMessage))
global.IPC.SetHandler(CmdMultipartMessage, ipc.TypedHandler(fnMultipartMessage))
@@ -228,7 +232,6 @@ func main() {
log.Err(err).Msg("Failed to close database")
}
log.Info().Msg("Shutdown preparations complete, exiting")
- os.Exit(0)
}
func initialConfigure(ctx context.Context) {
diff --git a/imessage/ffi/stdin.go b/imessage/ffi/stdin.go
new file mode 100644
index 0000000..0b2be40
--- /dev/null
+++ b/imessage/ffi/stdin.go
@@ -0,0 +1,41 @@
+// beeper-imessage - A Matrix-iMessage puppeting bridge.
+// Copyright (C) 2023 Beeper, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package main
+
+import "C"
+import (
+ "io"
+ "unsafe"
+)
+
+var FFIStdinReader, FFIStdinWriter = io.Pipe()
+
+// stdin_write is a function which allows C code to write to the fake "stdin"
+// buffer.
+//
+// This function returns the number of bytes written, or -1 if an error
+// occurred.
+//
+//export stdin_write
+func stdin_write(data *C.char, n C.int) C.int {
+ buf := C.GoBytes(unsafe.Pointer(data), n)
+ written, err := FFIStdinWriter.Write(buf)
+ if err != nil {
+ return C.int(-1)
+ }
+ return C.int(written)
+}
diff --git a/imessage/ffi/stdout.c b/imessage/ffi/stdout.c
new file mode 100644
index 0000000..f503c0a
--- /dev/null
+++ b/imessage/ffi/stdout.c
@@ -0,0 +1,7 @@
+#include
+
+typedef void (*stdout_callback_t)(const char *, int);
+
+void stdout_write(stdout_callback_t callback, const char *data, int n) {
+ callback(data, n);
+}
diff --git a/imessage/ffi/stdout.go b/imessage/ffi/stdout.go
new file mode 100644
index 0000000..9a1f0ca
--- /dev/null
+++ b/imessage/ffi/stdout.go
@@ -0,0 +1,44 @@
+// beeper-imessage - A Matrix-iMessage puppeting bridge.
+// Copyright (C) 2023 Beeper, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see .
+
+package main
+
+/*
+#include
+
+// stdout_callback is a function pointer to a function that takes a string and
+// returns nothing.
+typedef void (*stdout_callback_t)(const char*, int);
+void stdout_write(stdout_callback_t callback, const char* data, int n);
+*/
+import "C"
+import "unsafe"
+
+type ffiStdout struct {
+ callback C.stdout_callback_t
+}
+
+func (s *ffiStdout) Write(p []byte) (n int, err error) {
+ C.stdout_write(s.callback, (*C.char)(unsafe.Pointer(&p[0])), C.int(len(p)))
+ return len(p), nil
+}
+
+var FFIStdout = ffiStdout{}
+
+//export set_stdout_callback
+func set_stdout_callback(callback C.stdout_callback_t) {
+ FFIStdout.callback = callback
+}