Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/windows port finishing #25

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
go 1.21.6

use .
6 changes: 6 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/tailscale/hujson v0.0.0-20221223112325-20486734a56a/go.mod h1:DFSS3NAGHthKo1gTlmEcSBiZrRJXi28rLNd/1udP1c8=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
1,350 changes: 1,350 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dependencies": {
"express": "^4.18.2",
"ffi-napi": "^4.0.3",
"ref-napi": "^3.0.3"
}
}
33 changes: 33 additions & 0 deletions platform/tailscale_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//go:build darwin || linux
// +build darwin linux

package platform

//#include "errno.h"
//#include "../socketpair_handler.h"
import "C"

import (
"syscall"
)

func GetSocketPair() ([2]int, error) {
return syscall.Socketpair(syscall.AF_LOCAL, syscall.SOCK_STREAM, 0)
}

func CloseSocket(fd interface{}) (err error) {
return syscall.Close(fd.(int))
}

func ReadSocket(fd interface{}, buf *[256]byte) {
syscall.Read(fd.(int), (*buf)[:])
}

func SendMessage(fd interface{}, p []byte, connFd int, to syscall.Sockaddr, flags int) (err error) {
rights := syscall.UnixRights(int(connFd))
return syscall.Sendmsg(fd.(int), p, rights, to, flags)
}

func Shutdown(fd interface{}, how int) (err error) {
return syscall.Shutdown(fd.(int), how)
}
72 changes: 72 additions & 0 deletions platform/tailscale_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// If your file name follows the structure name_{GOOS}_{GOARCH}.go or
// simply name_{GOOS}.go,
// then it will be compiled only under the target OS+architecture
// or OS+any architecture respectively without needing a special comment
package platform

//#cgo CFLAGS: -g -Wall
//#cgo LDFLAGS: -lws2_32
//#include "errno.h"
//#include "../socketpair_handler.h"
import "C"

import (
"fmt"
"syscall"
"unsafe"
)

func GetSocketPair() ([]syscall.Handle, *C.SOCKET, error) {
fds := make([]syscall.Handle, 2)
fds_pt := C.get_socket_pair()
fds_array := (*[2]C.SOCKET)(unsafe.Pointer(fds_pt))[:]
fds[0] = syscall.Handle(uintptr(fds_array[0]))
fds[1] = syscall.Handle(uintptr(fds_array[1]))
return fds, fds_pt, nil
}

func CloseSocket(fd syscall.Handle) error {
fmt.Println("Closing socket", fd)
err := syscall.Close(fd)
if err != nil {
errCode := syscall.GetLastError()
// Handle the error or print it for debugging
fmt.Printf("Error closing handle: %v\n", err)
fmt.Printf("Errorcode: %v\n", errCode)
return err
}
fmt.Println("Closed socket", fd)
return nil
}

func ReadSocket(fd syscall.Handle, buf *[256]byte) {
fmt.Println("Reading socket", fd)
syscall.Read(fd, (*buf)[:])
}

func SendMessage(fd syscall.Handle, p []byte, connFd int, to syscall.Sockaddr, flags int) error {
fmt.Println("Writing socket", fd)
var written uint32
err := syscall.WSAStartup(uint32(0x202), &syscall.WSAData{})
if err != nil {
return err
}
defer syscall.WSACleanup()

iov := syscall.WSABuf{
Len: uint32(len(p)),
Buf: &p[0],
}
var flagsUint32 uint32 = uint32(flags)
err = syscall.WSASend(fd, &iov, 1, &written, flagsUint32, nil, nil)
if err != nil {
return err
}

return nil

}

func Shutdown(fd syscall.Handle, how int) error {
return syscall.Shutdown(fd, how)
}
162 changes: 162 additions & 0 deletions socketpair.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/* socketpair.c
Copyright 2007, 2010 by Nathan C. Myers <[email protected]>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

The name of the author must not be used to endorse or promote products
derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/* Changes:
* 2014-02-12: merge David Woodhouse, Ger Hobbelt improvements
* git.infradead.org/users/dwmw2/openconnect.git/commitdiff/bdeefa54
* github.com/GerHobbelt/selectable-socketpair
* always init the socks[] to -1/INVALID_SOCKET on error, both on Win32/64
* and UNIX/other platforms
* 2013-07-18: Change to BSD 3-clause license
* 2010-03-31:
* set addr to 127.0.0.1 because win32 getsockname does not always set it.
* 2010-02-25:
* set SO_REUSEADDR option to avoid leaking some windows resource.
* Windows System Error 10049, "Event ID 4226 TCP/IP has reached
* the security limit imposed on the number of concurrent TCP connect
* attempts." Bleah.
* 2007-04-25:
* preserve value of WSAGetLastError() on all error returns.
* 2007-04-22: (Thanks to Matthew Gregan <[email protected]>)
* s/EINVAL/WSAEINVAL/ fix trivial compile failure
* s/socket/WSASocket/ enable creation of sockets suitable as stdin/stdout
* of a child process.
* add argument make_overlapped
*/

#include <string.h>
#include <stdio.h>

#ifdef _WIN32
# include <ws2tcpip.h> /* socklen_t, et al (MSVC20xx) */
# include <windows.h>
# include <io.h>
#else
# include <sys/types.h>
# include <sys/socket.h>
# include <errno.h>
#endif

#ifdef _WIN32

/* dumb_socketpair:
* If make_overlapped is nonzero, both sockets created will be usable for
* "overlapped" operations via WSASend etc. If make_overlapped is zero,
* socks[0] (only) will be usable with regular ReadFile etc., and thus
* suitable for use as stdin or stdout of a child process. Note that the
* sockets must be closed with closesocket() regardless.
*/

static int dumb_socketpair(SOCKET socks[2], int make_overlapped)
{
union {
struct sockaddr_in inaddr;
struct sockaddr addr;
} a;
int iResult;
WSADATA wsaData;
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("failed WSA startup");
return SOCKET_ERROR;
}
SOCKET listener;
u_long mode = 1; // 1 to enable non-blocking socket
ioctlsocket(listener, FIONBIO, &mode);
int e;
socklen_t addrlen = sizeof(a.inaddr);
DWORD flags = (make_overlapped ? WSA_FLAG_OVERLAPPED : 0);
int reuse = 1;

if (socks == 0) {
WSASetLastError(WSAEINVAL);
return SOCKET_ERROR;
}
socks[0] = socks[1] = -1;
listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listener == -1) {
printf("%d", WSAGetLastError());
return SOCKET_ERROR;
}
memset(&a, 0, sizeof(a));
a.inaddr.sin_family = AF_INET;
a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
a.inaddr.sin_port = 0;

for (;;) {
if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR,
(char*) &reuse, (socklen_t) sizeof(reuse)) == -1)
break;
if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
break;

memset(&a, 0, sizeof(a));
if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR)
break;
// win32 getsockname may only set the port number, p=0.0005.
// ( http://msdn.microsoft.com/library/ms738543.aspx ):
a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
a.inaddr.sin_family = AF_INET;

if (listen(listener, 1) == SOCKET_ERROR)
break;

socks[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags);
if (socks[0] == -1)
break;
if (connect(socks[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR)
break;

socks[1] = accept(listener, NULL, NULL);
if (socks[1] == -1)
break;
WSACleanup();
closesocket(listener);
return 0;
}
e = WSAGetLastError();
closesocket(listener);
closesocket(socks[0]);
closesocket(socks[1]);
WSASetLastError(e);
socks[0] = socks[1] = -1;
WSACleanup();
return SOCKET_ERROR;
}
#else
static int dumb_socketpair(int socks[2], int dummy)
{
if (socks == 0) {
errno = EINVAL;
return -1;
}
dummy = socketpair(AF_LOCAL, SOCK_STREAM, 0, socks);
if (dummy)
socks[0] = socks[1] = -1;
return dummy;
}
#endif
32 changes: 32 additions & 0 deletions socketpair_handler.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifdef _WIN32
#include "socketpair_handler.h"
#include "socketpair.c"
#include <winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#endif

SOCKET *get_socket_pair() {
#ifdef _WIN32
SOCKET* spair = (SOCKET*)malloc(2 * sizeof(SOCKET));
if (spair == NULL) {
fprintf(stderr, "Failed to allocate memory for socket pair\n");
return NULL;
}

spair[0] = 0;
spair[1] = 0;
if(dumb_socketpair(spair, 1) == SOCKET_ERROR) {
fprintf(stderr, "Init failed, creating socketpair: %s\n", strerror(errno));
free(spair);
return NULL;
}
return spair;
#else
return NULL;
#endif


}
8 changes: 8 additions & 0 deletions socketpair_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef SOCKET_H
#define SOCKET_H

#include<winsock2.h>

SOCKET *get_socket_pair();

#endif
Loading