mirror of
https://github.com/zgs225/cliproxy-plugin-commandcode.git
synced 2026-09-26 03:32:50 +08:00
156 lines
3.9 KiB
Go
156 lines
3.9 KiB
Go
package main
|
|
|
|
/*
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
typedef struct {
|
|
void* ptr;
|
|
size_t len;
|
|
} cliproxy_buffer;
|
|
|
|
typedef int (*cliproxy_host_call_fn)(void*, const char*, const uint8_t*, size_t, cliproxy_buffer*);
|
|
typedef void (*cliproxy_host_free_fn)(void*, size_t);
|
|
|
|
typedef struct {
|
|
uint32_t abi_version;
|
|
void* host_ctx;
|
|
cliproxy_host_call_fn call;
|
|
cliproxy_host_free_fn free_buffer;
|
|
} cliproxy_host_api;
|
|
|
|
typedef int (*cliproxy_plugin_call_fn)(char*, uint8_t*, size_t, cliproxy_buffer*);
|
|
typedef void (*cliproxy_plugin_free_fn)(void*, size_t);
|
|
typedef void (*cliproxy_plugin_shutdown_fn)(void);
|
|
|
|
typedef struct {
|
|
uint32_t abi_version;
|
|
cliproxy_plugin_call_fn call;
|
|
cliproxy_plugin_free_fn free_buffer;
|
|
cliproxy_plugin_shutdown_fn shutdown;
|
|
} cliproxy_plugin_api;
|
|
|
|
extern int cliproxyPluginCall(char*, uint8_t*, size_t, cliproxy_buffer*);
|
|
extern void cliproxyPluginFree(void*, size_t);
|
|
extern void cliproxyPluginShutdown(void);
|
|
|
|
static const cliproxy_host_api* stored_host;
|
|
|
|
static void store_host_api(const cliproxy_host_api* host) {
|
|
stored_host = host;
|
|
}
|
|
|
|
static int call_host_api(const char* method, const uint8_t* request, size_t request_len, cliproxy_buffer* response) {
|
|
if (stored_host == NULL || stored_host->call == NULL) {
|
|
return 1;
|
|
}
|
|
return stored_host->call(stored_host->host_ctx, method, request, request_len, response);
|
|
}
|
|
|
|
static void free_host_buffer(void* ptr, size_t len) {
|
|
if (stored_host != NULL && stored_host->free_buffer != NULL && ptr != NULL) {
|
|
stored_host->free_buffer(ptr, len);
|
|
}
|
|
}
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"fmt"
|
|
"unsafe"
|
|
|
|
"github.com/zgs225/cliproxy-plugin-commandcode/plugin"
|
|
)
|
|
|
|
const abiVersion uint32 = 1
|
|
|
|
func main() {}
|
|
|
|
func init() {
|
|
plugin.SetHostCaller(callHost)
|
|
}
|
|
|
|
//export cliproxy_plugin_init
|
|
func cliproxy_plugin_init(host *C.cliproxy_host_api, pluginAPI *C.cliproxy_plugin_api) C.int {
|
|
if pluginAPI == nil {
|
|
return 1
|
|
}
|
|
C.store_host_api(host)
|
|
pluginAPI.abi_version = C.uint32_t(abiVersion)
|
|
pluginAPI.call = C.cliproxy_plugin_call_fn(C.cliproxyPluginCall)
|
|
pluginAPI.free_buffer = C.cliproxy_plugin_free_fn(C.cliproxyPluginFree)
|
|
pluginAPI.shutdown = C.cliproxy_plugin_shutdown_fn(C.cliproxyPluginShutdown)
|
|
return 0
|
|
}
|
|
|
|
//export cliproxyPluginCall
|
|
func cliproxyPluginCall(method *C.char, request *C.uint8_t, requestLen C.size_t, response *C.cliproxy_buffer) C.int {
|
|
if response != nil {
|
|
response.ptr = nil
|
|
response.len = 0
|
|
}
|
|
if method == nil {
|
|
writeResponse(response, plugin.ErrorEnvelope("invalid_method", "method is required"))
|
|
return 1
|
|
}
|
|
|
|
var requestBytes []byte
|
|
if request != nil && requestLen > 0 {
|
|
requestBytes = C.GoBytes(unsafe.Pointer(request), C.int(requestLen))
|
|
}
|
|
|
|
raw, errHandle := plugin.DefaultPlugin().HandleMethod(C.GoString(method), requestBytes)
|
|
if errHandle != nil {
|
|
writeResponse(response, plugin.ErrorEnvelope("plugin_error", errHandle.Error()))
|
|
return 1
|
|
}
|
|
|
|
writeResponse(response, raw)
|
|
return 0
|
|
}
|
|
|
|
//export cliproxyPluginFree
|
|
func cliproxyPluginFree(ptr unsafe.Pointer, len C.size_t) {
|
|
if ptr != nil {
|
|
C.free(ptr)
|
|
}
|
|
_ = len
|
|
}
|
|
|
|
//export cliproxyPluginShutdown
|
|
func cliproxyPluginShutdown() {}
|
|
|
|
func writeResponse(response *C.cliproxy_buffer, raw []byte) {
|
|
if response == nil || len(raw) == 0 {
|
|
return
|
|
}
|
|
ptr := C.CBytes(raw)
|
|
if ptr == nil {
|
|
return
|
|
}
|
|
response.ptr = ptr
|
|
response.len = C.size_t(len(raw))
|
|
}
|
|
|
|
func callHost(method string, payload []byte) ([]byte, error) {
|
|
cMethod := C.CString(method)
|
|
defer C.free(unsafe.Pointer(cMethod))
|
|
|
|
var response C.cliproxy_buffer
|
|
var req *C.uint8_t
|
|
if len(payload) > 0 {
|
|
req = (*C.uint8_t)(C.CBytes(payload))
|
|
defer C.free(unsafe.Pointer(req))
|
|
}
|
|
|
|
rc := C.call_host_api(cMethod, req, C.size_t(len(payload)), &response)
|
|
if rc != 0 {
|
|
return nil, fmt.Errorf("host call %s failed with code %d", method, int(rc))
|
|
}
|
|
if response.ptr == nil || response.len == 0 {
|
|
return nil, nil
|
|
}
|
|
defer C.free_host_buffer(response.ptr, response.len)
|
|
return C.GoBytes(response.ptr, C.int(response.len)), nil
|
|
}
|