Skip to content

Commit

Permalink
frontend: Sync Windows socket wrappers with backend.
Browse files Browse the repository at this point in the history
  • Loading branch information
Biswa96 committed Jan 22, 2021
1 parent 0acf699 commit ca6067c
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 163 deletions.
32 changes: 14 additions & 18 deletions src/Makefile.frontend
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# This file is part of wslbridge2 project.
# Licensed under the terms of the GNU General Public License v3 or later.
# Copyright (C) 2019-2020 Biswapriyo Nath.
# Copyright (C) 2019-2021 Biswapriyo Nath.

# Makefile for wslbridge2 frontend

STRIP ?= strip
NAME = wslbridge2.exe
BINDIR = ../bin
CFLAGS = -D_GNU_SOURCE -fno-exceptions -O2 -pedantic -std=c++11 -Wall
LFLAGS = -pthread
CFLAGS = -O2 -std=c99 -Wall -Wpedantic
CXXFLAGS = -D_GNU_SOURCE -fno-exceptions -O2 -std=c++11 -Wall -Wpedantic
LDFLAGS = -pthread

ifdef RELEASE
LFLAGS += -static -static-libgcc -static-libstdc++
LDFLAGS += -static -static-libgcc -static-libstdc++
endif

# DO NOT REMOVE ws2_32 library. This forces linker to use Windows socket
Expand All @@ -24,7 +24,7 @@ $(BINDIR)/common.obj \
$(BINDIR)/GetVmId.obj \
$(BINDIR)/Helpers.obj \
$(BINDIR)/TerminalState.obj \
$(BINDIR)/WindowsSock.obj \
$(BINDIR)/windows-sock.obj \
$(BINDIR)/wslbridge2.obj

# Windows header specific options
Expand All @@ -33,29 +33,25 @@ CCOPT = -D_WIN32_WINNT=0x0600 -DUNICODE -D_UNICODE
all : $(BINDIR) $(NAME)

$(NAME) : $(OBJS)
$(CXX) $^ $(LFLAGS) $(LIBS) -o $(BINDIR)/$@
$(STRIP) $(BINDIR)/$@
$(CXX) -s $^ $(LDFLAGS) $(LIBS) -o $(BINDIR)/$@

$(BINDIR)/common.obj : common.cpp
$(CXX) -c $(CFLAGS) $< -o $@
$(CXX) -c $(CXXFLAGS) $< -o $@

$(BINDIR)/GetVmId.obj : GetVmId.cpp
$(CXX) -c $(CFLAGS) $< -o $@
$(CXX) -c $(CXXFLAGS) $< -o $@

$(BINDIR)/Helpers.obj : Helpers.cpp
$(CXX) -c $(CFLAGS) $(CCOPT) $< -o $@

$(BINDIR)/LocalSock.obj : LocalSock.cpp
$(CXX) -c $(CFLAGS) $< -o $@
$(CXX) -c $(CXXFLAGS) $(CCOPT) $< -o $@

$(BINDIR)/TerminalState.obj : TerminalState.cpp
$(CXX) -c $(CFLAGS) $< -o $@
$(CXX) -c $(CXXFLAGS) $< -o $@

$(BINDIR)/WindowsSock.obj : WindowsSock.cpp
$(CXX) -c $(CFLAGS) $(CCOPT) $< -o $@
$(BINDIR)/windows-sock.obj : windows-sock.c
$(CC) -c $(CFLAGS) $< -o $@

$(BINDIR)/wslbridge2.obj : wslbridge2.cpp
$(CXX) -c $(CFLAGS) $(CCOPT) $< -o $@
$(CXX) -c $(CXXFLAGS) $(CCOPT) $< -o $@

$(BINDIR) :
mkdir -p $(BINDIR)
Expand Down
24 changes: 0 additions & 24 deletions src/WindowsSock.hpp

This file was deleted.

189 changes: 98 additions & 91 deletions src/WindowsSock.cpp → src/windows-sock.c
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/*
* This file is part of wslbridge2 project.
* Licensed under the terms of the GNU General Public License v3 or later.
* Copyright (C) 2019-2021 Biswapriyo Nath.
*/
// This file is part of wslbridge2 project.
// Licensed under the terms of the GNU General Public License v3 or later.
// Copyright (C) 2019-2021 Biswapriyo Nath.

// windows-sock.c: Wrappers for network functions in Windows side frontend.

#include <assert.h>
#include <stdbool.h>
#include <winsock2.h>
#include <hvsocket.h>
#include <assert.h>

#include "WindowsSock.hpp"
#include "windows-sock.h"

#ifndef AF_HYPERV
#define AF_HYPERV 34
Expand All @@ -22,33 +23,16 @@
#define RANDOMPORT() \
rand() % (DYNAMIC_PORT_HIGH - DYNAMIC_PORT_LOW) + DYNAMIC_PORT_LOW

void WindowsSock(void)
// Initialize Windows socket functionality.
void win_sock_init(void)
{
WSADATA wdata;
const int wsaRet = WSAStartup(MAKEWORD(2,2), &wdata);
assert(wsaRet == 0);
}

SOCKET CreateHvSock(void)
{
const SOCKET sock = WSASocketW(AF_HYPERV, SOCK_STREAM, HV_PROTOCOL_RAW,
NULL, 0, WSA_FLAG_OVERLAPPED);
assert(sock > 0);

const int suspend = true;
const int suspendRet = setsockopt(
sock,
HV_PROTOCOL_RAW,
HVSOCKET_CONNECTED_SUSPEND,
(char*)&suspend,
sizeof suspend);
assert(suspendRet == 0);

/* Return socket to caller */
return sock;
}

SOCKET CreateLocSock(void)
// Return IPv4 family socket.
SOCKET win_local_create(void)
{
const SOCKET sock = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP,
NULL, 0, WSA_FLAG_OVERLAPPED);
Expand All @@ -63,118 +47,141 @@ SOCKET CreateLocSock(void)
(const char *)&flag, sizeof flag);
assert(reuseRet == 0);

/* Return socket to caller */
return sock;
}

SOCKET AcceptHvSock(const SOCKET sock)
{
const SOCKET cSock = WSAAccept(sock, NULL, NULL, NULL, 0);
assert(cSock > 0);

/* Server socket is no longer needed. */
closesocket(sock);
return cSock;
}

SOCKET AcceptLocSock(const SOCKET sock)
// Accept IPv4 socket and return accepted socket.
SOCKET win_local_accept(const SOCKET sock)
{
const SOCKET cSock = WSAAccept(sock, NULL, NULL, NULL, 0);
assert(cSock > 0);
const SOCKET acceptSock = WSAAccept(sock, NULL, NULL, NULL, 0);
assert(acceptSock > 0);

const int flag = true;
const int nodelayRet = setsockopt(cSock, IPPROTO_TCP, TCP_NODELAY,
const int nodelayRet = setsockopt(acceptSock, IPPROTO_TCP, TCP_NODELAY,
(const char *)&flag, sizeof flag);
assert(nodelayRet == 0);

const int reuseRet = setsockopt(cSock, SOL_SOCKET, SO_REUSEADDR,
const int reuseRet = setsockopt(acceptSock, SOL_SOCKET, SO_REUSEADDR,
(const char *)&flag, sizeof flag);
assert(reuseRet == 0);

/* Server socket is no longer needed. */
// Server socket is no longer needed.
closesocket(sock);
return cSock;
return acceptSock;
}

void ConnectHvSock(const SOCKET sock, const GUID *VmId, const int port)
// Create and connect with a localhost socket and return it.
SOCKET win_local_connect(const unsigned short port)
{
const int timeout = 10 * 1000; /* Ten seconds */
const int timeRet = setsockopt(
sock,
HV_PROTOCOL_RAW,
HVSOCKET_CONNECT_TIMEOUT,
(char*)&timeout,
sizeof timeout);
assert(timeRet == 0);
const SOCKET sock = win_local_create();

SOCKADDR_HV addr = {};
addr.Family = AF_HYPERV;
memcpy(&addr.VmId, VmId, sizeof addr.VmId);
memcpy(&addr.ServiceId, &HV_GUID_VSOCK_TEMPLATE, sizeof addr.ServiceId);
addr.ServiceId.Data1 = port;
const int connectRet = WSAConnect(sock, (sockaddr*)&addr, sizeof addr,
NULL, NULL, NULL, NULL);
// Connect to a specific port and localhost address.
struct sockaddr_in addr = { 0 };
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
const int connectRet = WSAConnect(sock, (const struct sockaddr *)&addr,
sizeof addr, NULL, NULL, NULL, NULL);
assert(connectRet == 0);

return sock;
}

void ConnectLocSock(const SOCKET sock, const USHORT port)
// Listen to a localhost socket and return the port.
int win_local_listen(const SOCKET sock, const unsigned short port)
{
struct sockaddr_in addr = { 0 };
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
const int bindRet = bind(sock, (struct sockaddr *)&addr, sizeof addr);
assert(bindRet == 0);

// Listen for only one connection.
const int listenRet = listen(sock, 1);
assert(listenRet == 0);

int addrLen = sizeof addr;
const int getRet = getsockname(sock, (struct sockaddr *)&addr, &addrLen);
assert(getRet == 0);

// Return port number to caller.
return ntohs(addr.sin_port);
}

// Return hyperv family socket.
SOCKET win_vsock_create(void)
{
const SOCKET sock = WSASocketW(AF_HYPERV, SOCK_STREAM, HV_PROTOCOL_RAW,
NULL, 0, WSA_FLAG_OVERLAPPED);
assert(sock > 0);

const int suspend = true;
const int suspendRet = setsockopt(sock, HV_PROTOCOL_RAW, HVSOCKET_CONNECTED_SUSPEND,
(const char *)&suspend, sizeof suspend);
assert(suspendRet == 0);

return sock;
}

// Accept hyperv socket and return accepted socket.
SOCKET win_vsock_accept(const SOCKET sock)
{
const SOCKET acceptSock = WSAAccept(sock, NULL, NULL, NULL, 0);
assert(acceptSock > 0);

// Server socket is no longer needed.
closesocket(sock);
return acceptSock;
}

// Create and connect with a hyperv socket and return it.
SOCKET win_vsock_connect(const GUID *VmId, const unsigned int port)
{
const SOCKET sock = win_vsock_create();

const int timeout = 10 * 1000; // Ten seconds.
const int timeRet = setsockopt(sock, HV_PROTOCOL_RAW, HVSOCKET_CONNECT_TIMEOUT,
(const char *)&timeout, sizeof timeout);
assert(timeRet == 0);

SOCKADDR_HV addr = { 0 };
addr.Family = AF_HYPERV;
memcpy(&addr.VmId, VmId, sizeof addr.VmId);
memcpy(&addr.ServiceId, &HV_GUID_VSOCK_TEMPLATE, sizeof addr.ServiceId);
addr.ServiceId.Data1 = port;
const int connectRet = WSAConnect(sock, (const struct sockaddr *)&addr,
sizeof addr, NULL, NULL, NULL, NULL);
assert(connectRet == 0);

return sock;
}

int ListenHvSock(const SOCKET sock, const GUID *VmId)
// Listen to a hyperv socket and return the port.
int win_vsock_listen(const SOCKET sock, const GUID *VmId)
{
SOCKADDR_HV addr = {};
SOCKADDR_HV addr = { 0 };
addr.Family = AF_HYPERV;
memcpy(&addr.VmId, VmId, sizeof addr.VmId);
memcpy(&addr.ServiceId, &HV_GUID_VSOCK_TEMPLATE, sizeof addr.ServiceId);

/* Try to bind to a dynamic port */
//wslbridge2 #2: Try to bind to a dynamic port, AF_HYPERV can not.
int nretries = 0, port = 0;

while (nretries < BIND_MAX_RETRIES)
{
port = RANDOMPORT();
addr.ServiceId.Data1 = port;
const int bindRet = bind(sock, (sockaddr*)&addr, sizeof addr);
const int bindRet = bind(sock, (struct sockaddr *)&addr, sizeof addr);
if (bindRet == 0)
break;

nretries++;
}

/* Listen for only one connection. */
// Listen for only one connection.
const int listenRet = listen(sock, 1);
assert(listenRet == 0);

/* Return port number to caller */
return port;
}

int ListenLocSock(const SOCKET sock, const USHORT port)
{
/* Bind to any available port */
sockaddr_in addr = {};
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
const int bindRet = bind(sock, (sockaddr*)&addr, sizeof addr);
assert(bindRet == 0);

/* Listen for only one connection. */
const int listenRet = listen(sock, 1);
assert(listenRet == 0);

int addrLen = sizeof addr;
const int getRet = getsockname(sock, (sockaddr*)&addr, &addrLen);
assert(getRet == 0);

/* Return port number to caller */
return ntohs(addr.sin_port);
}
Loading

0 comments on commit ca6067c

Please sign in to comment.