xref: /unit/go/unit.go (revision 1713:f5ba5973a0a3)
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