summaryrefslogtreecommitdiffhomepage
path: root/go/unit.go
diff options
context:
space:
mode:
Diffstat (limited to 'go/unit.go')
-rw-r--r--go/unit.go149
1 files changed, 149 insertions, 0 deletions
diff --git a/go/unit.go b/go/unit.go
new file mode 100644
index 00000000..1534479e
--- /dev/null
+++ b/go/unit.go
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) Max Romanov
+ * Copyright (C) NGINX, Inc.
+ */
+
+package unit
+
+/*
+#include "nxt_cgo_lib.h"
+*/
+import "C"
+
+import (
+ "fmt"
+ "net/http"
+ "sync"
+ "unsafe"
+)
+
+type cbuf struct {
+ b C.uintptr_t
+ s C.size_t
+}
+
+func buf_ref(buf []byte) C.uintptr_t {
+ if len(buf) == 0 {
+ return 0
+ }
+
+ return C.uintptr_t(uintptr(unsafe.Pointer(&buf[0])))
+}
+
+type StringHeader struct {
+ Data unsafe.Pointer
+ Len int
+}
+
+func str_ref(s string) C.uintptr_t {
+ header := (*StringHeader)(unsafe.Pointer(&s))
+
+ return C.uintptr_t(uintptr(unsafe.Pointer(header.Data)))
+}
+
+func (buf *cbuf) init_bytes(b []byte) {
+ buf.b = buf_ref(b)
+ buf.s = C.size_t(len(b))
+}
+
+func (buf *cbuf) init_string(s string) {
+ buf.b = str_ref(s)
+ buf.s = C.size_t(len(s))
+}
+
+type SliceHeader struct {
+ Data unsafe.Pointer
+ Len int
+ Cap int
+}
+
+func (buf *cbuf) GoBytes() []byte {
+ if buf == nil {
+ var b [0]byte
+ return b[:0]
+ }
+
+ bytesHeader := &SliceHeader{
+ Data: unsafe.Pointer(uintptr(buf.b)),
+ Len: int(buf.s),
+ Cap: int(buf.s),
+ }
+
+ return *(*[]byte)(unsafe.Pointer(bytesHeader))
+}
+
+func GoBytes(buf unsafe.Pointer, size C.int) []byte {
+ bytesHeader := &SliceHeader{
+ Data: buf,
+ Len: int(size),
+ Cap: int(size),
+ }
+
+ return *(*[]byte)(unsafe.Pointer(bytesHeader))
+}
+
+func nxt_go_warn(format string, args ...interface{}) {
+ str := fmt.Sprintf("[go] " + format, args...)
+
+ C.nxt_cgo_warn(str_ref(str), C.uint32_t(len(str)))
+}
+
+type handler_registry struct {
+ sync.RWMutex
+ next uintptr
+ m map[uintptr]*http.Handler
+}
+
+var handler_registry_ handler_registry
+
+func set_handler(handler *http.Handler) uintptr {
+
+ handler_registry_.Lock()
+ if handler_registry_.m == nil {
+ handler_registry_.m = make(map[uintptr]*http.Handler)
+ handler_registry_.next = 1
+ }
+
+ h := handler_registry_.next
+ handler_registry_.next += 1
+ handler_registry_.m[h] = handler
+
+ handler_registry_.Unlock()
+
+ return h
+}
+
+func get_handler(h uintptr) http.Handler {
+ handler_registry_.RLock()
+ defer handler_registry_.RUnlock()
+
+ return *handler_registry_.m[h]
+}
+
+func reset_handler(h uintptr) {
+
+ handler_registry_.Lock()
+ if handler_registry_.m != nil {
+ delete(handler_registry_.m, h)
+ }
+
+ handler_registry_.Unlock()
+}
+
+func ListenAndServe(addr string, handler http.Handler) error {
+ if handler == nil {
+ handler = http.DefaultServeMux
+ }
+
+ h := set_handler(&handler)
+
+ rc := C.nxt_cgo_run(C.uintptr_t(h))
+
+ reset_handler(h)
+
+ if rc != 0 {
+ return http.ListenAndServe(addr, handler)
+ }
+
+ return nil
+}