summaryrefslogblamecommitdiffhomepage
path: root/src/go/unit/unit.go
blob: 1534479ec3cd7134ef8930f653f104317e39ffed (plain) (tree)
1
2
3
4
5
6
7
8
9




                            
            

  
                        




             
                  
              



                  
                     
                  

 
                                      
                          
                        

         
                                                            

 


                           

 

                                                     
 
                                                                

 


                                       

 


                                        

 



                           

 



                                   

         



                                                     

         

                                                      
 




                                                     

         

                                                      
 

                                                      
 

                                                          
 









































                                                                     


                                                              
         
 




                                           
 

                                                         

         
                  
 
/*
 * 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
}