11316Smax.romanov@nginx.com/* 21316Smax.romanov@nginx.com * Copyright (C) Max Romanov 31316Smax.romanov@nginx.com * Copyright (C) NGINX, Inc. 41316Smax.romanov@nginx.com */ 51316Smax.romanov@nginx.com 61316Smax.romanov@nginx.compackage unit 71316Smax.romanov@nginx.com 81316Smax.romanov@nginx.com/* 91316Smax.romanov@nginx.com#include "nxt_cgo_lib.h" 101316Smax.romanov@nginx.com*/ 111316Smax.romanov@nginx.comimport "C" 121316Smax.romanov@nginx.com 131316Smax.romanov@nginx.comimport ( 141316Smax.romanov@nginx.com "fmt" 151316Smax.romanov@nginx.com "net/http" 161316Smax.romanov@nginx.com "sync" 171316Smax.romanov@nginx.com "unsafe" 181316Smax.romanov@nginx.com) 191316Smax.romanov@nginx.com 201316Smax.romanov@nginx.comtype cbuf struct { 211316Smax.romanov@nginx.com b C.uintptr_t 221316Smax.romanov@nginx.com s C.size_t 231316Smax.romanov@nginx.com} 241316Smax.romanov@nginx.com 251316Smax.romanov@nginx.comfunc buf_ref(buf []byte) C.uintptr_t { 261316Smax.romanov@nginx.com if len(buf) == 0 { 271316Smax.romanov@nginx.com return 0 281316Smax.romanov@nginx.com } 291316Smax.romanov@nginx.com 301316Smax.romanov@nginx.com return C.uintptr_t(uintptr(unsafe.Pointer(&buf[0]))) 311316Smax.romanov@nginx.com} 321316Smax.romanov@nginx.com 33*1713Smax.romanov@nginx.comtype string_header struct { 341316Smax.romanov@nginx.com Data unsafe.Pointer 351316Smax.romanov@nginx.com Len int 361316Smax.romanov@nginx.com} 371316Smax.romanov@nginx.com 38*1713Smax.romanov@nginx.comfunc str_ref(s string) *C.char { 39*1713Smax.romanov@nginx.com header := (*string_header)(unsafe.Pointer(&s)) 401316Smax.romanov@nginx.com 41*1713Smax.romanov@nginx.com return (*C.char)(header.Data) 421316Smax.romanov@nginx.com} 431316Smax.romanov@nginx.com 441316Smax.romanov@nginx.comfunc (buf *cbuf) init_bytes(b []byte) { 451316Smax.romanov@nginx.com buf.b = buf_ref(b) 461316Smax.romanov@nginx.com buf.s = C.size_t(len(b)) 471316Smax.romanov@nginx.com} 481316Smax.romanov@nginx.com 49*1713Smax.romanov@nginx.comtype slice_header struct { 501316Smax.romanov@nginx.com Data unsafe.Pointer 511316Smax.romanov@nginx.com Len int 521316Smax.romanov@nginx.com Cap int 531316Smax.romanov@nginx.com} 541316Smax.romanov@nginx.com 551316Smax.romanov@nginx.comfunc (buf *cbuf) GoBytes() []byte { 561316Smax.romanov@nginx.com if buf == nil { 571316Smax.romanov@nginx.com var b [0]byte 581316Smax.romanov@nginx.com return b[:0] 591316Smax.romanov@nginx.com } 601316Smax.romanov@nginx.com 61*1713Smax.romanov@nginx.com header := &slice_header{ 621316Smax.romanov@nginx.com Data: unsafe.Pointer(uintptr(buf.b)), 631316Smax.romanov@nginx.com Len: int(buf.s), 641316Smax.romanov@nginx.com Cap: int(buf.s), 651316Smax.romanov@nginx.com } 661316Smax.romanov@nginx.com 67*1713Smax.romanov@nginx.com return *(*[]byte)(unsafe.Pointer(header)) 681316Smax.romanov@nginx.com} 691316Smax.romanov@nginx.com 701316Smax.romanov@nginx.comfunc GoBytes(buf unsafe.Pointer, size C.int) []byte { 71*1713Smax.romanov@nginx.com bytesHeader := &slice_header{ 721316Smax.romanov@nginx.com Data: buf, 731316Smax.romanov@nginx.com Len: int(size), 741316Smax.romanov@nginx.com Cap: int(size), 751316Smax.romanov@nginx.com } 761316Smax.romanov@nginx.com 771316Smax.romanov@nginx.com return *(*[]byte)(unsafe.Pointer(bytesHeader)) 781316Smax.romanov@nginx.com} 791316Smax.romanov@nginx.com 80*1713Smax.romanov@nginx.comfunc GoStringN(sptr *C.nxt_unit_sptr_t, l C.int) string { 81*1713Smax.romanov@nginx.com p := unsafe.Pointer(sptr) 82*1713Smax.romanov@nginx.com b := uintptr(p) + uintptr(*(*C.uint32_t)(p)) 83*1713Smax.romanov@nginx.com 84*1713Smax.romanov@nginx.com return C.GoStringN((*C.char)(unsafe.Pointer(b)), l) 85*1713Smax.romanov@nginx.com} 86*1713Smax.romanov@nginx.com 871316Smax.romanov@nginx.comfunc nxt_go_warn(format string, args ...interface{}) { 881316Smax.romanov@nginx.com str := fmt.Sprintf("[go] " + format, args...) 891316Smax.romanov@nginx.com 901316Smax.romanov@nginx.com C.nxt_cgo_warn(str_ref(str), C.uint32_t(len(str))) 911316Smax.romanov@nginx.com} 921316Smax.romanov@nginx.com 93*1713Smax.romanov@nginx.comfunc nxt_go_alert(format string, args ...interface{}) { 94*1713Smax.romanov@nginx.com str := fmt.Sprintf("[go] " + format, args...) 95*1713Smax.romanov@nginx.com 96*1713Smax.romanov@nginx.com C.nxt_cgo_alert(str_ref(str), C.uint32_t(len(str))) 97*1713Smax.romanov@nginx.com} 98*1713Smax.romanov@nginx.com 991316Smax.romanov@nginx.comtype handler_registry struct { 1001316Smax.romanov@nginx.com sync.RWMutex 1011316Smax.romanov@nginx.com next uintptr 1021316Smax.romanov@nginx.com m map[uintptr]*http.Handler 1031316Smax.romanov@nginx.com} 1041316Smax.romanov@nginx.com 1051316Smax.romanov@nginx.comvar handler_registry_ handler_registry 1061316Smax.romanov@nginx.com 1071316Smax.romanov@nginx.comfunc set_handler(handler *http.Handler) uintptr { 1081316Smax.romanov@nginx.com 1091316Smax.romanov@nginx.com handler_registry_.Lock() 1101316Smax.romanov@nginx.com if handler_registry_.m == nil { 1111316Smax.romanov@nginx.com handler_registry_.m = make(map[uintptr]*http.Handler) 1121316Smax.romanov@nginx.com handler_registry_.next = 1 1131316Smax.romanov@nginx.com } 1141316Smax.romanov@nginx.com 1151316Smax.romanov@nginx.com h := handler_registry_.next 1161316Smax.romanov@nginx.com handler_registry_.next += 1 1171316Smax.romanov@nginx.com handler_registry_.m[h] = handler 1181316Smax.romanov@nginx.com 1191316Smax.romanov@nginx.com handler_registry_.Unlock() 1201316Smax.romanov@nginx.com 1211316Smax.romanov@nginx.com return h 1221316Smax.romanov@nginx.com} 1231316Smax.romanov@nginx.com 1241316Smax.romanov@nginx.comfunc get_handler(h uintptr) http.Handler { 1251316Smax.romanov@nginx.com handler_registry_.RLock() 1261316Smax.romanov@nginx.com defer handler_registry_.RUnlock() 1271316Smax.romanov@nginx.com 1281316Smax.romanov@nginx.com return *handler_registry_.m[h] 1291316Smax.romanov@nginx.com} 1301316Smax.romanov@nginx.com 1311316Smax.romanov@nginx.comfunc reset_handler(h uintptr) { 1321316Smax.romanov@nginx.com 1331316Smax.romanov@nginx.com handler_registry_.Lock() 1341316Smax.romanov@nginx.com if handler_registry_.m != nil { 1351316Smax.romanov@nginx.com delete(handler_registry_.m, h) 1361316Smax.romanov@nginx.com } 1371316Smax.romanov@nginx.com 1381316Smax.romanov@nginx.com handler_registry_.Unlock() 1391316Smax.romanov@nginx.com} 1401316Smax.romanov@nginx.com 1411316Smax.romanov@nginx.comfunc ListenAndServe(addr string, handler http.Handler) error { 1421316Smax.romanov@nginx.com if handler == nil { 1431316Smax.romanov@nginx.com handler = http.DefaultServeMux 1441316Smax.romanov@nginx.com } 1451316Smax.romanov@nginx.com 1461316Smax.romanov@nginx.com h := set_handler(&handler) 1471316Smax.romanov@nginx.com 1481316Smax.romanov@nginx.com rc := C.nxt_cgo_run(C.uintptr_t(h)) 1491316Smax.romanov@nginx.com 1501316Smax.romanov@nginx.com reset_handler(h) 1511316Smax.romanov@nginx.com 1521316Smax.romanov@nginx.com if rc != 0 { 1531316Smax.romanov@nginx.com return http.ListenAndServe(addr, handler) 1541316Smax.romanov@nginx.com } 1551316Smax.romanov@nginx.com 1561316Smax.romanov@nginx.com return nil 1571316Smax.romanov@nginx.com} 158