1/* 2 * Copyright (C) Max Romanov 3 * Copyright (C) NGINX, Inc. 4 */ 5 6package unit 7 8/* 9#include "nxt_cgo_lib.h" 10*/ 11import "C" 12 13import ( 14 "fmt" 15 "net/http" 16 "sync" 17 "unsafe" 18) 19 20type cbuf struct { 21 b C.uintptr_t 22 s C.size_t 23} 24 25func buf_ref(buf []byte) C.uintptr_t { 26 if len(buf) == 0 { 27 return 0 28 } 29 30 return C.uintptr_t(uintptr(unsafe.Pointer(&buf[0]))) 31} 32 33type StringHeader struct { 34 Data unsafe.Pointer 35 Len int 36} 37 38func str_ref(s string) C.uintptr_t { 39 header := (*StringHeader)(unsafe.Pointer(&s)) 40 41 return C.uintptr_t(uintptr(unsafe.Pointer(header.Data))) 42} 43 44func (buf *cbuf) init_bytes(b []byte) { 45 buf.b = buf_ref(b) 46 buf.s = C.size_t(len(b)) 47} 48 49func (buf *cbuf) init_string(s string) { 50 buf.b = str_ref(s) 51 buf.s = C.size_t(len(s)) 52} 53 54type SliceHeader struct { 55 Data unsafe.Pointer 56 Len int 57 Cap int 58} 59 60func (buf *cbuf) GoBytes() []byte { 61 if buf == nil { 62 var b [0]byte 63 return b[:0] 64 } 65 66 bytesHeader := &SliceHeader{ 67 Data: unsafe.Pointer(uintptr(buf.b)), 68 Len: int(buf.s), 69 Cap: int(buf.s), 70 } 71 72 return *(*[]byte)(unsafe.Pointer(bytesHeader)) 73} 74 75func GoBytes(buf unsafe.Pointer, size C.int) []byte { 76 bytesHeader := &SliceHeader{ 77 Data: buf, 78 Len: int(size), 79 Cap: int(size), 80 } 81 82 return *(*[]byte)(unsafe.Pointer(bytesHeader)) 83} 84 85func nxt_go_warn(format string, args ...interface{}) { 86 str := fmt.Sprintf("[go] " + format, args...) 87 88 C.nxt_cgo_warn(str_ref(str), C.uint32_t(len(str))) 89} 90 91type handler_registry struct { 92 sync.RWMutex 93 next uintptr 94 m map[uintptr]*http.Handler 95} 96 97var handler_registry_ handler_registry 98 99func set_handler(handler *http.Handler) uintptr { 100 101 handler_registry_.Lock() 102 if handler_registry_.m == nil { 103 handler_registry_.m = make(map[uintptr]*http.Handler) 104 handler_registry_.next = 1 105 } 106 107 h := handler_registry_.next 108 handler_registry_.next += 1 109 handler_registry_.m[h] = handler 110 111 handler_registry_.Unlock() 112 113 return h 114} 115 116func get_handler(h uintptr) http.Handler { 117 handler_registry_.RLock() 118 defer handler_registry_.RUnlock() 119 120 return *handler_registry_.m[h] 121} 122 123func reset_handler(h uintptr) { 124 125 handler_registry_.Lock() 126 if handler_registry_.m != nil { 127 delete(handler_registry_.m, h) 128 } 129 130 handler_registry_.Unlock() 131} 132 133func ListenAndServe(addr string, handler http.Handler) error { 134 if handler == nil { 135 handler = http.DefaultServeMux 136 } 137 138 h := set_handler(&handler) 139 140 rc := C.nxt_cgo_run(C.uintptr_t(h)) 141 142 reset_handler(h) 143 144 if rc != 0 { 145 return http.ListenAndServe(addr, handler) 146 } 147 148 return nil 149} 150