Skip to content

Commit

Permalink
android: ipc -> ffi
Browse files Browse the repository at this point in the history
This commit converts the stdin/stdout IPC interface to use FFI using
emulated stdin/stdout.

Signed-off-by: Sumner Evans <[email protected]>
  • Loading branch information
sumnerevans committed Dec 20, 2023
1 parent 7c700e3 commit 688129a
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@
/beeper-imessage
/start
/.android-ipc-bin
/imgo.h
/imgo.so
3 changes: 1 addition & 2 deletions android-ipc → android-ffi
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion android/imessage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 4 additions & 0 deletions imessage/ipc/events.go → imessage/ffi/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion imessage/ipc/global.go → imessage/ffi/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down
File renamed without changes.
11 changes: 7 additions & 4 deletions imessage/ipc/main.go → imessage/ffi/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package main

import "C"
import (
"context"
_ "embed"
Expand Down Expand Up @@ -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
})
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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) {
Expand Down
41 changes: 41 additions & 0 deletions imessage/ffi/stdin.go
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

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)
}
7 changes: 7 additions & 0 deletions imessage/ffi/stdout.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <stdio.h>

typedef void (*stdout_callback_t)(const char *, int);

void stdout_write(stdout_callback_t callback, const char *data, int n) {
callback(data, n);
}
44 changes: 44 additions & 0 deletions imessage/ffi/stdout.go
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.

package main

/*
#include <stdio.h>
// 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
}

0 comments on commit 688129a

Please sign in to comment.