diff options
Diffstat (limited to 'go/unit.go')
-rw-r--r-- | go/unit.go | 149 |
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 +} |