xref: /unit/go/unit.go (revision 1316:5b767c6bfd0a)
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