diff --git a/Makefile b/Makefile index 65767d0..32aff40 100755 --- a/Makefile +++ b/Makefile @@ -190,6 +190,7 @@ darwin-gz: env darwin ## build darwin packages ## unit test test: ## execute unit test + go clean -testcache go test -v -mod=vendor -bench=. github.com/luscis/openlan/pkg/access go test -v -mod=vendor -bench=. github.com/luscis/openlan/pkg/libol go test -v -mod=vendor -bench=. github.com/luscis/openlan/pkg/models diff --git a/pkg/libol/udp.go b/pkg/libol/udp.go new file mode 100644 index 0000000..c684da7 --- /dev/null +++ b/pkg/libol/udp.go @@ -0,0 +1,176 @@ +package libol + +/* +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + u_int32_t padding[2]; + u_int32_t spi; + u_int32_t seqno; +} udp_message; + +typedef struct { + u_int16_t port; + int32_t socket; +} udp_server; + +typedef struct { + int32_t socket; + uint16_t remote_port; + const char *remote_addr; + u_int32_t spi; + u_int32_t seqno; +} udp_connection; + +int seqno = 0; + +int send_ping_once(udp_connection *conn) { + int retval = 0; + struct sockaddr_in dstaddr = { + .sin_family = AF_INET, + .sin_port = htons(conn->remote_port), + .sin_addr = { + .s_addr = inet_addr(conn->remote_addr), + }, + }; + udp_message data = { + .padding = {0, 0}, + .spi = htonl(conn->spi), + }; + data.seqno = htonl(conn->seqno++); + + retval = sendto(conn->socket, &data, sizeof data, 0, (struct sockaddr *)&dstaddr, sizeof dstaddr); + if (retval <= 0) { + printf("%s: could not send data\n", conn->remote_addr); + } + + return retval; +} + +int recv_ping_once(udp_connection *conn, udp_connection *from) { + struct sockaddr_in addr; + int addrlen = sizeof addr; + udp_message data; + int datalen = sizeof data; + int retval = 0; + + memset(&data, 0, sizeof data); + retval = recvfrom(conn->socket, &data, datalen, 0, (struct sockaddr *)&addr, &addrlen); + if ( retval <= 0 ) { + if (errno == EAGAIN) { + return 0; + } + printf("recvfrom: %s\n", strerror(errno)); + return retval; + } + + from->spi = ntohl(data.spi); + from->remote_addr = inet_ntoa(addr.sin_addr); + from->remote_port = ntohs(addr.sin_port); + + return retval; +} + +int open_socket(udp_server *srv) { + int op = 1; + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_port = htons(srv->port), + .sin_addr = { + .s_addr = INADDR_ANY, + }, + }; + int retval = 0; + + srv->socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (srv->socket == -1) { + return -1; + } + + retval = setsockopt(srv->socket, SOL_SOCKET, SO_REUSEADDR, &op, sizeof op); + if (retval < 0) { + return -1; + } + retval = bind(srv->socket, (struct sockaddr *)&addr, sizeof addr); + if ( retval == -1) { + return -1; + } + + return 0; +} + +int configure_socket(udp_server *srv) { + int encap = UDP_ENCAP_ESPINUDP; + + if (setsockopt(srv->socket, IPPROTO_UDP, UDP_ENCAP, &encap, sizeof encap) < 0) { + return -1; + } + return 0; +} +*/ +import "C" +import ( + "fmt" + "sync" + "time" + "unsafe" +) + +func StartUDP(spi uint32, port uint16, remote string) { + server := &C.udp_server{ + port: C.ushort(port), + socket : -1, + } + _ = C.open_socket(server) + C.configure_socket(server) + + addr := C.CString(remote) + defer C.free(unsafe.Pointer(addr)) + conn := &C.udp_connection { + socket: server.socket, + spi: C.uint(spi), + remote_port: C.ushort(port), + remote_addr: addr, + } + + C.send_ping_once(conn) + + w := sync.WaitGroup{} + w.Add(2) + Go(func() { + defer w.Done() + for i := 0; i < 100; i++ { + time.Sleep(time.Second) + C.send_ping_once(conn) + } + }) + + Go(func() { + from := &C.udp_connection{} + C.recv_ping_once(conn, from) + addr := C.GoString(from.remote_addr) + fmt.Printf("receive from %s:%d spi %d\n", addr, from.remote_port, from.spi) + w.Done() + for { + from := &C.udp_connection{} + C.recv_ping_once(conn, from) + addr := C.GoString(from.remote_addr) + fmt.Printf("receive from %s:%d spi %d\n", addr, from.remote_port, from.spi) + } + }) + + w.Wait() +} \ No newline at end of file diff --git a/pkg/libol/udp_test.go b/pkg/libol/udp_test.go new file mode 100644 index 0000000..d6d64c0 --- /dev/null +++ b/pkg/libol/udp_test.go @@ -0,0 +1,9 @@ +package libol + +import ( + "testing" +) + +func TestStartUDP_C(t *testing.T) { + StartUDP(84209, 4500, "180.109.49.146") +}