<|start_filename|>node/config/global.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package config

import (
	"os"

	"github.com/pairmesh/pairmesh/constant"
)

// APIGateway returns the gateway address. The PAIRMESH_GATEWAY_API environment variable
// will be prioritized to be returned to the caller. And the default gateway address
// will be used if no customized address found.
func APIGateway() string {
	if g, found := os.LookupEnv("PAIRMESH_GATEWAY_API"); found {
		return g
	}
	return constant.DefaultAPIGateway
}

// MyGateway returns the gateway address. The PAIRMESH_GATEWAY_MY environment variable
// will be prioritized to be returned to the caller. And the default gateway address
// will be used if no customized address found.
func MyGateway() string {
	if g, found := os.LookupEnv("PAIRMESH_GATEWAY_MY"); found {
		return g
	}
	return constant.DefaultMyGateway
}


<|start_filename|>node/device/router_linux.go<|end_filename|>
package device

import (
	"github.com/pairmesh/pairmesh/node/device/runner"

	"inet.af/netaddr"
)

func (r *router) add(devName string, localAddress netaddr.IP, target netaddr.IPPrefix) error {
	args := []string{
		"ip",
		"route",
		"add",
		target.Masked().String(),
		"via",
		localAddress.String(),
	}
	return runner.Run(args)
}

func (r *router) del(devName string, localAddress netaddr.IP, target netaddr.IPPrefix) error {
	args := []string{
		"ip",
		"route",
		"del",
		target.Masked().String(),
		"via",
		localAddress.String(),
	}
	return runner.Run(args)
}


<|start_filename|>node/mesh/tunnel/interface.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tunnel

import "net"

// FragmentCallback represents the callback of receiving fragment data.
type FragmentCallback interface {
	// OnFragment will be called if there are fragments received from the
	// low-level mesh network.
	OnFragment(data []byte)
}

// UDPPacketCallback represents the callback of UDP packets.
// There are two ways to read UDP packets:
// 1. UDP packets from relay server (PacketConnect/PacketFragment/Other system packets).
// 2. UDP packets from peers (PacketKeepalive/PacketFragment).
type UDPPacketCallback interface {
	// OnUDPPacket will be called if there are UDP packets received from
	// the low-level UDPConn connections.
	OnUDPPacket(udpConn *net.UDPConn, data []byte)
}


<|start_filename|>portal/webui/src/console/main.js<|end_filename|>
// Copyright 2022 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Vue from 'vue'
import Console from './app'
import Overview from '@/console/components/overview'
import Networks from '@/console/components/networks'
import Keys from '@/console/components/keys'
import Settings from '@/console/components/settings'
import Member from '@/console/components/member'
import '@/plugins/element.js'
import '@/console/components/flexbox'
import '@/plugins/vue-router'
import VueRouter from "vue-router";

const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/console/overview',
            component: Overview,
        },
        {
            path: '/console/networks',
            component: Networks,
        },
        {
            path: '/console/network/:network_id',
            component: Member,
        },
        {
            path: '/console/keys',
            component: Keys,
        },
        {
            path: '/console/settings',
            component: Settings,
        }
    ],
})

new Vue({
    router,
    el: '#app',
    render: h => h(Console)
});


<|start_filename|>node/device/firewall/firewall_windows.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package firewall

import (
	"fmt"
	"os"
	"os/exec"
	"syscall"
	"time"

	"go.uber.org/zap"
)

const (
	firewallNameIn      = "PairMesh-In"
	firewallNameProcess = "PairMesh-Process"
)

func Setup(addr string) {
	// Clear all firewall rules
	begin := time.Now()

	// Clear previous firewall rules.
	clear()

	defer func() {
		zap.L().Info("Setup the firewall rules", zap.Duration("duration", time.Since(begin)))
	}()

	exe, err := os.Executable()
	if err != nil {
		zap.L().Error("Cannot retrieve the executable", zap.Error(err))
	}

	processRule := []string{
		"advfirewall",
		"firewall",
		"add",
		"rule",
		"name=" + firewallNameProcess,
		"dir=in",
		"action=allow",
		"edge=yes",
		fmt.Sprintf("program=\"%s\"", exe),
		"protocol=udp",
		"profile=any",
		"enable=yes",
	}

	cmd := exec.Command("netsh", processRule...)
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}

	out, err := cmd.CombinedOutput()
	if err != nil {
		zap.L().Error("Setup the firewall rules(PairMesh-Process) failed", zap.Error(err), zap.String("output", string(out)))
	}

	localAddrRule := []string{
		"advfirewall",
		"firewall",
		"add",
		"rule",
		"name=" + firewallNameIn,
		"dir=in",
		"action=allow",
		"localip=" + addr,
		"profile=any",
		"enable=yes",
	}

	cmd = exec.Command("netsh", localAddrRule...)
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}

	out, err = cmd.CombinedOutput()
	if err != nil {
		zap.L().Error("Setup the firewall rules(PairMesh-In) failed", zap.Error(err), zap.String("output", string(out)))
	}
}

func clear() {
	// Clear all firewall rules
	begin := time.Now()

	defer func() {
		zap.L().Info("Clear the firewall rules", zap.Duration("duration", time.Since(begin)))
	}()

	clearIn := []string{
		"advfirewall",
		"firewall",
		"delete",
		"rule",
		"name=" + firewallNameIn,
		"dir=in",
	}

	cmd := exec.Command("netsh", clearIn...)
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}

	out, err := cmd.CombinedOutput()
	if err != nil {
		zap.L().Error("Clear the firewall rules(PairMesh-In) failed", zap.Error(err), zap.String("output", string(out)))
	}

	clearProcess := []string{
		"advfirewall",
		"firewall",
		"delete",
		"rule",
		"name=" + firewallNameProcess,
		"dir=in",
	}
	cmd = exec.Command("netsh", clearProcess...)
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}

	out, err = cmd.CombinedOutput()
	if err != nil {
		zap.L().Error("Clear the firewall rules(PairMesh-Process) failed", zap.Error(err), zap.String("output", string(out)))
	}
}


<|start_filename|>node/entry/systray/systray_c.go<|end_filename|>
package systray

/*
   #cgo darwin CFLAGS: -DDARWIN -x objective-c -fobjc-arc
   #cgo darwin LDFLAGS: -framework Cocoa
   #include "systray.h"
*/
import "C"

import (
	"unsafe"
)

func register_systray() {
	C.register_systray()
}

func native_loop() {
	C.native_loop()
}

func quit() {
	C.quit()
}

// SetIcon sets the systray icon.
// iconBytes should be the content of .ico for windows and .ico/.jpg/.png
// for other platforms.
func SetIcon(iconBytes []byte) {
	cstr := (*C.char)(unsafe.Pointer(&iconBytes[0]))
	C.set_icon(cstr, (C.int)(len(iconBytes)), false)
}

// SetTitle sets the systray title, only available on Mac and Linux.
func SetTitle(title string) {
	C.set_title(C.CString(title))
}

func addSeparator(id uint32) {
	C.add_separator(C.int(id))
}

func hideMenuItem(item *MenuItem) {
	C.hide_menu_item(
		C.int(item.id),
	)
}

func showMenuItem(item *MenuItem) {
	C.show_menu_item(
		C.int(item.id),
	)
}

func removeAllItems(item *MenuItem) {
	C.remove_all_items(
		C.int(item.id),
	)
}

//export systray_ready
func systray_ready() {
	systrayReady()
}

//export systray_on_exit
func systray_on_exit() {
	systrayExit()
}

//export systray_menu_item_selected
func systray_menu_item_selected(cID C.int) {
	systrayMenuItemSelected(uint32(cID))
}

// update propagates changes on a menu item to systray
func (item *MenuItem) update() {
	var disabled C.short
	if item.disabled {
		disabled = 1
	}
	var checked C.short
	if item.checked {
		checked = 1
	}
	C.upsert_menu_item(
		C.int(item.id),
		C.int(0),
		C.int(0),
		C.CString(item.title),
		disabled,
		checked,
	)
}

// insert propagates changes on a menu item to systray
func (item *MenuItem) insert(parentID, siblingID uint32) {
	var disabled C.short
	if item.disabled {
		disabled = 1
	}
	var checked C.short
	if item.checked {
		checked = 1
	}
	C.upsert_menu_item(
		C.int(item.id),
		C.int(parentID),
		C.int(siblingID),
		C.CString(item.title),
		disabled,
		checked,
	)
}


<|start_filename|>node/device/tun/tun_darwin.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tun

import (
	"fmt"
	"io"
	"os"
	"sync"
	"syscall"
	"unsafe"

	"github.com/pkg/errors"
	"golang.org/x/sys/unix"
)

const appleUTUNCtl = "com.apple.net.utun_control"

/*
 * From ioctl.h:
 * #define	IOCPARM_MASK	0x1fff		// parameter length, at most 13 bits
 * ...
 * #define	IOC_OUT		0x40000000	// copy out parameters
 * #define	IOC_IN		0x80000000	// copy in parameters
 * #define	IOC_INOUT	(IOC_IN|IOC_OUT)
 * ...
 * #define _IOC(inout,group,num,len) \
 * 	(inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num))
 * ...
 * #define	_IOWR(g,n,t)	_IOC(IOC_INOUT,	(g), (n), sizeof(t))
 *
 * From kern_control.h:
 * #define CTLIOCGINFO     _IOWR('N', 3, struct ctl_info)	// get id from name
 *
 */

const appleCTLIOCGINFO = (0x40000000 | 0x80000000) | ((100 & 0x1fff) << 16) | uint32(byte('N'))<<8 | 3

/*
 * #define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t))
 * #define TUNSIFMODE _IOW('t', 94, int)
 */
const appleTUNSIFMODE = (0x80000000) | ((4 & 0x1fff) << 16) | uint32(byte('t'))<<8 | 94

/*
 * struct sockaddr_ctl {
 *     u_char sc_len; // depends on size of bundle ID string
 *     u_char sc_family; // AF_SYSTEM
 *     u_int16_t ss_sysaddr; // AF_SYS_KERNCONTROL
 *     u_int32_t sc_id; // Controller unique identifier
 *     u_int32_t sc_unit; // Developer private unit number
 *     u_int32_t sc_reserved[5];
 * };
 */
type sockaddrCtl struct {
	scLen      uint8
	scFamily   uint8
	ssSysaddr  uint16
	scID       uint32
	scUnit     uint32
	scReserved [5]uint32
}

var sockaddrCtlSize uintptr = 32

// NewTUN creates a new TUN device and set the address to the specified address
func NewTUN() (Device, error) {

	// Supposed to be socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), but ...
	//
	// In sys/socket.h:
	// #define PF_SYSTEM	AF_SYSTEM
	//
	// In sys/sys_domain.h:
	// #define SYSPROTO_CONTROL       	2	/* kernel control protocol */
	fd, err := syscall.Socket(syscall.AF_SYSTEM, syscall.SOCK_DGRAM, 2)
	if err != nil {
		return nil, fmt.Errorf("error in syscall.Socket: %v", err)
	}

	var ctlInfo = &struct {
		ctlID   uint32
		ctlName [96]byte
	}{}
	copy(ctlInfo.ctlName[:], appleUTUNCtl)

	_, _, errno := syscall.Syscall(
		syscall.SYS_IOCTL,
		uintptr(fd),
		uintptr(appleCTLIOCGINFO),
		uintptr(unsafe.Pointer(ctlInfo)),
	)
	if errno != 0 {
		err = errno
		return nil, fmt.Errorf("error in syscall.Syscall(syscall.SYS_IOCTL, ...): %v", err)
	}

	addrP := unsafe.Pointer(&sockaddrCtl{
		scLen:    uint8(sockaddrCtlSize),
		scFamily: syscall.AF_SYSTEM,

		/* #define AF_SYS_CONTROL 2 */
		ssSysaddr: 2,
		scID:      ctlInfo.ctlID,
	})

	_, _, errno = syscall.RawSyscall(
		syscall.SYS_CONNECT,
		uintptr(fd),
		uintptr(addrP),
		uintptr(sockaddrCtlSize),
	)
	if errno != 0 {
		err = errno
		return nil, fmt.Errorf("error in syscall.RawSyscall(syscall.SYS_CONNECT, ...): %v", err)
	}

	var ifName struct {
		name [16]byte
	}
	ifNameSize := uintptr(16)
	if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd),
		2, /* #define SYSPROTO_CONTROL 2 */
		2, /* #define UTUN_OPT_IFNAME 2 */
		uintptr(unsafe.Pointer(&ifName)),
		uintptr(unsafe.Pointer(&ifNameSize)), 0); errno != 0 {
		err = errno
		return nil, fmt.Errorf("error in syscall.Syscall6(syscall.SYS_GETSOCKOPT, ...): %v", err)
	}

	if err := setNonBlock(fd); err != nil {
		return nil, fmt.Errorf("setting non-blocking error")
	}

	name := string(ifName.name[:ifNameSize-1 /* -1 is for \0 */])

	dev := &generalDevice{
		name: name,
		ReadWriteCloser: &tunReadCloser{
			f: os.NewFile(uintptr(fd), string(ifName.name[:])),
		},
	}

	setmtu := func() error {
		fd, err := unix.Socket(
			unix.AF_INET,
			unix.SOCK_DGRAM,
			0,
		)

		if err != nil {
			return err
		}

		defer unix.Close(fd)

		var ifr unix.IfreqMTU
		copy(ifr.Name[:], name)
		ifr.MTU = int32(DefaultMTU)
		err = unix.IoctlSetIfreqMTU(fd, &ifr)
		if err != nil {
			return fmt.Errorf("failed to set MTU on %s: %w", name, err)
		}

		return nil
	}
	if err := setmtu(); err != nil {
		return nil, err
	}

	return dev, nil
}

// tunReadCloser is a hack to work around the first 4 bytes "packet
// information" because there doesn't seem to be an IFF_NO_PI for darwin.
type tunReadCloser struct {
	f io.ReadWriteCloser

	rMu  sync.Mutex
	rBuf []byte

	wMu  sync.Mutex
	wBuf []byte
}

var _ io.ReadWriteCloser = (*tunReadCloser)(nil)

func (t *tunReadCloser) Read(to []byte) (int, error) {
	t.rMu.Lock()
	defer t.rMu.Unlock()

	if cap(t.rBuf) < len(to)+4 {
		t.rBuf = make([]byte, len(to)+4)
	}
	t.rBuf = t.rBuf[:len(to)+4]

	n, err := t.f.Read(t.rBuf)
	copy(to, t.rBuf[4:])
	return n - 4, err
}

func (t *tunReadCloser) Write(from []byte) (int, error) {
	if len(from) == 0 {
		return 0, syscall.EIO
	}

	t.wMu.Lock()
	defer t.wMu.Unlock()

	if cap(t.wBuf) < len(from)+4 {
		t.wBuf = make([]byte, len(from)+4)
	}
	t.wBuf = t.wBuf[:len(from)+4]

	// Determine the IP Family for the NULL L2 Header
	ipVer := from[0] >> 4
	if ipVer == 4 {
		t.wBuf[3] = syscall.AF_INET
	} else if ipVer == 6 {
		t.wBuf[3] = syscall.AF_INET6
	} else {
		return 0, errors.New("Unable to determine IP version from packet")
	}

	copy(t.wBuf[4:], from)

	n, err := t.f.Write(t.wBuf)
	return n - 4, err
}

func (t *tunReadCloser) Close() error {
	return t.f.Close()
}


<|start_filename|>node/entry/systray/registry.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package systray

import "sync"

var globalRegistry = newRegistry()

// registry is used to store all menu items.
type registry struct {
	mu     sync.RWMutex
	items  map[uint32]*MenuItem
	events chan *MenuItem
}

// newRegistry returns a new registry instance.
func newRegistry() *registry {
	return &registry{
		items:  map[uint32]*MenuItem{},
		events: make(chan *MenuItem, 64),
	}
}

// Store stores the item to the registry and the old one will be overwrited.
func (r *registry) Store(item *MenuItem) {
	r.mu.Lock()
	r.items[item.id] = item
	r.mu.Unlock()
}

// MenuItem returns the MenuItem corresponding to the id.
func (r *registry) MenuItem(id uint32) *MenuItem {
	r.mu.RLock()
	item := r.items[id]
	r.mu.RUnlock()
	return item
}

// Events returns the events list.
func Events() <-chan *MenuItem {
	return globalRegistry.events
}


<|start_filename|>pkg/jwt/option.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package jwt

import "time"

// AccessDetails represents a helper object for manage jwt token
type AccessDetails struct {
	UserID     uint64
	AccessUUID string
	MachineID  string
	AuthKeyID  uint64
}

// TokenDetails represents a full object about the  jwt token
type TokenDetails struct {
	AccessToken   string
	RefreshToken  string
	AccessUUID    string
	RefreshUUID   string
	AccessExpiry  int64
	RefreshExpiry int64
}

// Option represents a handler for adjust the default option(s)
type Option func(*options)

type options struct {
	store           Store
	accessTokenTTL  time.Duration
	refreshTokenTTL time.Duration

	accessSecret  string
	refreshSecret string
}

func newOptions(opts ...Option) options {
	opt := options{
		accessTokenTTL:  time.Minute * 1500,
		refreshTokenTTL: time.Hour * 24 * 7,
		store: memoryStore{
			m: map[string]interface{}{},
		},
	}

	for _, o := range opts {
		o(&opt)
	}

	return opt
}

// AccessTokenTTL adjust the access token's ttl in seconds
func AccessTokenTTL(seconds uint32) Option {
	return func(o *options) {
		if seconds == 0 {
			return
		}
		o.accessTokenTTL = time.Duration(seconds) * time.Second
	}
}

// RefreshTokenTTL adjust the refresh token's ttl in seconds
func RefreshTokenTTL(seconds uint32) Option {
	return func(o *options) {
		if seconds == 0 {
			return
		}
		o.refreshTokenTTL = time.Duration(seconds) * time.Second
	}
}

// WithStore adjust the default store for jwt token
func WithStore(s Store) Option {
	return func(o *options) {
		if s == nil {
			return
		}
		o.store = s
	}
}


<|start_filename|>internal/relay/security_transporter_test.go<|end_filename|>
// Copyright 2022 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package relay

import (
	"crypto/rand"
	"testing"

	"github.com/pairmesh/pairmesh/security"
	"github.com/stretchr/testify/assert"
)

func TestSecurityTransporter_Cipher(t *testing.T) {
	key, err := security.CipherSuite.GenerateKeypair(rand.Reader)
	assert.Nil(t, err)

	dhk, err := security.CipherSuite.DH(key.Private, key.Public)
	assert.Nil(t, err)

	fixSizeKey := [32]byte{}
	copy(fixSizeKey[:], dhk)
	trs := newSecurityTransporter(nil)
	cipher := security.CipherSuite.Cipher(fixSizeKey)
	trs.SetCipher(cipher)

	// The cipher is not a comparable object, so we encrypt/decrypt data to identify they are same.
	nonce := uint64(12345)
	text := []byte("hello world!")
	encrypted := cipher.Encrypt(nil, nonce, nil, text)
	decrypted, err := cipher.Decrypt(nil, nonce, nil, encrypted)
	assert.Nil(t, err)

	assert.Equal(t, text, decrypted)
}


<|start_filename|>relay/server/stun.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"context"
	"errors"
	"net"
	"os"
	"sync"
	"time"

	"github.com/pairmesh/pairmesh/internal/stun"
	"github.com/pairmesh/pairmesh/pkg/logutil"
	"github.com/pairmesh/pairmesh/relay/config"
	"go.uber.org/zap"
)

func serveSTUN(ctx context.Context, cfg *config.Config, wg *sync.WaitGroup) {
	defer wg.Done()

	addr := &net.UDPAddr{
		Port: cfg.STUNPort,
	}
	udpConn, err := net.ListenUDP("udp", addr)
	if err != nil {
		zap.L().Fatal("Open STUN listener is failed", zap.Error(err))
	}
	zap.L().Info("The STUN server is running", zap.Any("addr", udpConn.LocalAddr()))

	var buf [64 << 10]byte

	serveProtocol := func() error {
		_ = udpConn.SetReadDeadline(time.Now().Add(3 * time.Second))
		n, remote, err := udpConn.ReadFromUDP(buf[:])
		if err != nil {
			if errors.Is(err, os.ErrDeadlineExceeded) {
				return nil
			}
			return err
		}

		if logutil.IsEnableRelay() {
			zap.L().Debug("Read UDP packet", zap.Stringer("remote", remote))
		}

		data := buf[:n]
		if !stun.Is(data) {
			return errors.New("not stun packet")
		}

		txid, err := stun.ParseBindingRequest(data)
		if err != nil {
			return err
		}

		res := stun.Response(txid, remote.IP, uint16(remote.Port))
		_, err = udpConn.WriteToUDP(res, remote)

		return err
	}

	for {
		select {
		case <-ctx.Done():
			zap.L().Info("The STUN server is over")
			return

		default:
			err := serveProtocol()
			if err != nil {
				zap.L().Error("RelayServer stun failed", zap.Error(err))
			}
		}
	}
}


<|start_filename|>node/device/runner/run_command.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package runner

import (
	"errors"
	"fmt"
	"os/exec"
	"strings"
	"time"

	"go.uber.org/zap"
)

// Run runs the command with arguments.
func Run(args []string) error {
	if len(args) == 0 {
		return errors.New("cmd: no argv[0]")
	}

	start := time.Now()
	defer func() {
		zap.L().Debug("Run command", zap.Strings("cmd", args), zap.Duration("duration", time.Since(start)))
	}()

	cmd := attr(exec.Command(args[0], args[1:]...))
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("running %q failed: %w\n%s", strings.Join(args, " "), err, out)
	}

	return nil
}


<|start_filename|>build/Makefile.gen.mk<|end_filename|>
# Generate the database query interfaces.
queryset:
	go run ./tools/qs/main.go -in ./portal/db/models/models.go -out ./portal/db/models/autogen_query.go

# Generate the protocol buffer files
proto:
	@cd message/protos; \
    protoc --go_out=. *.proto; \
    protoc --go-grpc_out=. *.proto


<|start_filename|>security/credential.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package security

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha256"
	"encoding/binary"
	"net"
	"time"

	"github.com/pairmesh/pairmesh/protocol"
)

const (
	credentialValidationHeaderSize = 25
)

// Credential returns a credential to identity the Peer, which contains
// the expiration time and the reclaimed IP address. All requests relevant
// to IP address, the credential is required. We will verify the triple:
// -> (PeerID, IP, Expiration).
// The schema of credential:
// |   PeerID    |  PeerID    |  Expiration  |  IPLen  |    IP     |
// |  8 bytes    | 8 bytes    |    8 bytes   |  1 byte |  Variant  |
// The credential delivered to the client will be encrypted by secret key.
// The secret key is a private key only held by the gateway.
func Credential(privateKey *rsa.PrivateKey, userID protocol.UserID, peerID protocol.PeerID, ip net.IP, lease time.Duration) ([]byte, error) {
	data := make([]byte, credentialValidationHeaderSize+len(ip))
	binary.BigEndian.PutUint64(data[:8], uint64(userID))
	binary.BigEndian.PutUint64(data[8:16], uint64(peerID))
	expirationAt := time.Now().Add(lease).Unix()
	binary.BigEndian.PutUint64(data[16:24], uint64(expirationAt))
	data[credentialValidationHeaderSize-1] = byte(len(ip))
	copy(data[credentialValidationHeaderSize:credentialValidationHeaderSize+len(ip)], ip)

	digest := sha256.Sum256(data[:])
	signed, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, digest[:])
	if err != nil {
		return nil, err
	}
	credential := append(data[:], signed...)
	return credential, nil
}

// VerifyCredential verifies the expiration of the credential, returns the networkID, peerID and IP
func VerifyCredential(publicKey *rsa.PublicKey, credential []byte) (userID protocol.UserID, peerID protocol.PeerID, ip net.IP, valid bool) {
	// Illegal credentials
	if len(credential) <= credentialValidationHeaderSize+net.IPv4len {
		return 0, 0, nil, false
	}

	ipLen := credential[credentialValidationHeaderSize-1]

	digest := sha256.Sum256(credential[:credentialValidationHeaderSize+ipLen])
	err := rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, digest[:], credential[credentialValidationHeaderSize+ipLen:])
	if err != nil {
		return 0, 0, nil, false
	}

	// expiration
	if time.Now().Unix() > int64(binary.BigEndian.Uint64(credential[16:credentialValidationHeaderSize-1])) {
		return 0, 0, nil, false
	}
	userID = protocol.UserID(binary.BigEndian.Uint64(credential[:8]))
	peerID = protocol.PeerID(binary.BigEndian.Uint64(credential[8:16]))
	ip = credential[credentialValidationHeaderSize : credentialValidationHeaderSize+ipLen]
	return userID, peerID, ip, true
}


<|start_filename|>node/driver/local_addresses.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package driver

import (
	"net"
	"runtime"
	"sort"
	"strings"

	"go.uber.org/zap"
	"inet.af/netaddr"
)

func isUp(iface *net.Interface) bool       { return iface.Flags&net.FlagUp != 0 }
func isLoopback(iface *net.Interface) bool { return iface.Flags&net.FlagLoopback != 0 }
func isProblematicInterface(iface *net.Interface) bool {
	name := iface.Name

	// Don't try to send disco/etc packets over zerotier; they effectively
	// DoS each other by doing traffic amplification, both of them
	// preferring/trying to use each other for transport. See:
	// https://github.com/tailscale/tailscale/issues/1208
	if strings.HasPrefix(name, "zt") || (runtime.GOOS == "windows" && strings.Contains(name, "ZeroTier")) {
		return true
	}

	if strings.HasPrefix(name, "ts") || (runtime.GOOS == "windows" && strings.Contains(name, "TailScale")) {
		return true
	}

	return false
}

// localAddresses detects the local interfaces and returns all the IP addresses
// belongs to current node.
func (d *NodeDriver) localAddresses() []string {
	ifaces, err := net.Interfaces()
	if err != nil {
		zap.L().Error("Retrieve the interfaces failed", zap.Error(err))
		return nil
	}

	var localAddresses []netaddr.IP

	for i := range ifaces {
		iface := &ifaces[i]
		if !isUp(iface) || isProblematicInterface(iface) {
			// Skip down interfaces and ones that are
			// problematic that we don't want to try to
			// send Tailscale traffic over.
			continue
		}

		ifcIsLoopback := isLoopback(iface)
		if ifcIsLoopback {
			continue
		}

		addrs, err := iface.Addrs()
		if err != nil {
			zap.L().Error("Retrieve interface addresses failed",
				zap.String("interface", iface.Name), zap.Error(err))
			continue
		}

		for _, a := range addrs {
			v, ok := a.(*net.IPNet)
			if !ok {
				continue
			}

			ip, ok := netaddr.FromStdIP(v.IP)
			if !ok {
				continue
			}

			if ip.Is6() {
				continue
			}

			if ip.String() == d.credential.address {
				continue
			}

			localAddresses = append(localAddresses, ip)
		}
	}

	sort.Slice(localAddresses, func(i, j int) bool {
		return localAddresses[i].Less(localAddresses[j])
	})

	// Deduplicate
	var addresses []string
	for _, a := range localAddresses {
		addr := a.String()
		if len(addresses) == 0 || (len(addresses) > 0 && addresses[len(addresses)-1] != addr) {
			addresses = append(addresses, addr)
		}
	}

	return addresses
}


<|start_filename|>portal/webui/src/login/main.js<|end_filename|>
// Copyright 2022 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import Vue from 'vue'
import App from './app.vue'
import '@/plugins/element.js'
import '@/plugins/vue-router'
import VueRouter from "vue-router";
import Login from "@/login/components/login";
import AuthCallback from "@/login/components/auth_callback";
import AuthRedirect from "@/login/components/auth_redirect";
import AuthSuccess from "@/login/components/auth_success";

const router = new VueRouter({
    mode: 'history',
    routes: [
        {
            path: '/login',
            component: Login,
        },
        {
            path: '/login/auth/callback/github',
            component: AuthCallback,
        },
        {
            path: '/login/auth/redirect',
            component: AuthRedirect,
        },
        {
            path: '/login/auth/success',
            component: AuthSuccess,
        }
    ],
})

new Vue({
    router,
    el: '#app',
    render: h => h(App)
});


<|start_filename|>node/device/router_windows.go<|end_filename|>
package device

import (
	"github.com/pairmesh/pairmesh/node/device/runner"

	"inet.af/netaddr"
)

func (r *router) add(_ string, localAddress netaddr.IP, target netaddr.IPPrefix) error {
	args := []string{
		"route",
		"add",
		target.IP().String(),
		"mask",
		target.Masked().String(),
		localAddress.String(),
	}
	return runner.Run(args)
}

func (r *router) del(_ string, _ netaddr.IP, target netaddr.IPPrefix) error {
	args := []string{
		"route",
		"delete ",
		target.IP().String(),
		"mask",
		target.Masked().String(),
	}
	return runner.Run(args)
}


<|start_filename|>portal/db/logger.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package db

import (
	"context"
	"fmt"
	"time"

	"github.com/pairmesh/pairmesh/pkg/logutil"
	"go.uber.org/zap"
	"gorm.io/gorm/logger"
)

// Logger is the customized logger for gorm
type Logger struct {
	level logger.LogLevel
}

// LogMode implements the logger.Interface interface
func (l *Logger) LogMode(level logger.LogLevel) logger.Interface {
	l.level = level
	return l
}

// Info implements the logger.Interface interface
func (l *Logger) Info(_ context.Context, format string, args ...interface{}) {
	if l.level < logger.Info {
		return
	}
	zap.L().Info(fmt.Sprintf(format, args...))
}

// Warn implements the logger.Interface interface
func (l *Logger) Warn(_ context.Context, format string, args ...interface{}) {
	if l.level < logger.Warn {
		return
	}
	zap.L().Warn(fmt.Sprintf(format, args...))
}

// Error implements the logger.Interface interface
func (l *Logger) Error(_ context.Context, format string, args ...interface{}) {
	if l.level < logger.Error {
		return
	}
	zap.L().Error(fmt.Sprintf(format, args...))
}

// Trace implements the logger.Interface interface
func (l *Logger) Trace(_ context.Context, _ time.Time, fc func() (string, int64), err error) {
	if logutil.IsEnablePortal() {
		sql, _ := fc()
		if err != nil {
			zap.L().Error("GORM Trace",
				zap.String("SQL", sql),
				zap.Error(err))
		} else {
			zap.L().Debug("GORM Trace",
				zap.String("SQL", sql),
				zap.Error(err))
		}
	}
}


<|start_filename|>internal/messagebox/cocoa/dlg.h<|end_filename|>
#include <objc/NSObjCRuntime.h>

typedef enum {
	MSG_YESNO,
	MSG_ERROR,
	MSG_INFO,
} AlertStyle;

typedef struct {
	char* msg;
	char* title;
	AlertStyle style;
} AlertDlgParams;

typedef enum {
	DLG_OK,
	DLG_CANCEL,
	DLG_URLFAIL,
} DlgResult;

DlgResult alertDlg(AlertDlgParams*);

void* NSStr(void* buf, int len);
void NSRelease(void* obj);


<|start_filename|>tools/qs/main.go<|end_filename|>
package main

import (
	"context"
	"flag"
	"log"
	"path/filepath"
	"time"

	"github.com/pairmesh/pairmesh/tools/qs/internal/parser"
	"github.com/pairmesh/pairmesh/tools/qs/internal/queryset/generator"
)

func main() {
	const defaultOutPath = "autogenerated_{in}"

	inFile := flag.String("in", "models.go", "path to input file")
	outFile := flag.String("out", defaultOutPath, "path to output file")
	timeout := flag.Duration("timeout", time.Minute, "timeout for generation")
	flag.Parse()

	if *outFile == defaultOutPath {
		*outFile = filepath.Join(filepath.Dir(*inFile), "autogenerated_"+filepath.Base(*inFile))
	}

	g := generator.Generator{
		StructsParser: &parser.Structs{},
	}

	ctx, finish := context.WithTimeout(context.Background(), *timeout)
	defer finish()

	if err := g.Generate(ctx, *inFile, *outFile); err != nil {
		log.Fatalf("can't generate query sets: %s", err)
	}
}


<|start_filename|>codec/peer_codec_test.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package codec

import (
	"testing"

	"github.com/flynn/noise"
	"github.com/pairmesh/pairmesh/message"
	"github.com/pairmesh/pairmesh/protocol"
	"github.com/stretchr/testify/assert"
)

type RandomInc byte

func (r *RandomInc) Read(p []byte) (int, error) {
	for i := range p {
		p[i] = byte(*r)
		*r = (*r) + 1
	}
	return len(p), nil
}

func TestEncode(t *testing.T) {
	key, err := noise.DH25519.GenerateKeypair(new(RandomInc))
	assert.Nil(t, err)

	// The encrypt/decrypt cipher of tunnels are the same.
	sharedKey, err := noise.DH25519.DH(key.Private, key.Public)
	assert.Nil(t, err)

	fixSizeKey := [32]byte{}
	copy(fixSizeKey[:], sharedKey)
	cipher := noise.CipherChaChaPoly.Cipher(fixSizeKey)

	peerID := protocol.PeerID(1234567)
	data := []byte{1, 2, 3, 4, 5}

	encoded := Encode(message.PacketType_Handshake, cipher, peerID, data)
	nonce, typ, pid, payload, err := Decode(encoded)
	assert.Nil(t, err)

	assert.Equal(t, typ, message.PacketType_Handshake)
	assert.Equal(t, pid, peerID)

	decrypted, err := cipher.Decrypt(nil, uint64(nonce), nil, payload)
	assert.Nil(t, err)
	assert.Equal(t, decrypted, data)
}


<|start_filename|>node/device/tun/wintun/ddl.go<|end_filename|>
//go:build windows

// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/* SPDX-License-Identifier: MIT
 *
 * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved.
 */

package wintun

import (
	"fmt"
	"sync"
	"sync/atomic"
	"unsafe"

	"github.com/pairmesh/pairmesh/node/device/tun/wintun/embed"
	"github.com/pairmesh/pairmesh/node/device/tun/wintun/memmod"
)

func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL {
	return &lazyDLL{Name: name, onLoad: onLoad}
}

func (d *lazyDLL) NewProc(name string) *lazyProc {
	return &lazyProc{dll: d, Name: name}
}

type lazyProc struct {
	Name string
	mu   sync.Mutex
	dll  *lazyDLL
	addr uintptr
}

func (p *lazyProc) Find() error {
	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr))) != nil {
		return nil
	}
	p.mu.Lock()
	defer p.mu.Unlock()
	if p.addr != 0 {
		return nil
	}

	err := p.dll.Load()
	if err != nil {
		return fmt.Errorf("Error loading %v DLL: %w", p.dll.Name, err)
	}
	addr, err := p.nameToAddr()
	if err != nil {
		return fmt.Errorf("Error getting %v address: %w", p.Name, err)
	}

	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr)), unsafe.Pointer(addr))
	return nil
}

func (p *lazyProc) Addr() uintptr {
	err := p.Find()
	if err != nil {
		panic(err)
	}
	return p.addr
}

type lazyDLL struct {
	Name   string
	mu     sync.Mutex
	module *memmod.Module
	onLoad func(d *lazyDLL)
}

func (d *lazyDLL) Load() error {
	if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
		return nil
	}
	d.mu.Lock()
	defer d.mu.Unlock()
	if d.module != nil {
		return nil
	}

	module, err := memmod.LoadLibrary(embed.DLLBytes())
	if err != nil {
		return fmt.Errorf("unable to load library: %w", err)
	}

	atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
	if d.onLoad != nil {
		d.onLoad(d)
	}
	return nil
}

func (p *lazyProc) nameToAddr() (uintptr, error) {
	return p.dll.module.ProcAddressByName(p.Name)
}

// Version returns the version of the Wintun DLL.
func Version() string {
	return wintunDDLVersion
}


<|start_filename|>node/entry/systray/systray.h<|end_filename|>
#include "stdbool.h"

extern void systray_ready();
extern void systray_on_exit();
extern void systray_menu_item_selected(int menu_id);
void register_systray(void);
int native_loop(void);

void set_icon(const char* iconBytes, int length, bool template);
void set_title(char* title);
void remove_all_items(int menuId);
void upsert_menu_item(int menuId, int parentMenuId, int siblingId, char* title, short disabled, short checked);
void add_separator(int menuId);
void hide_menu_item(int menuId);
void show_menu_item(int menuId);
void quit();


<|start_filename|>tools/qs/internal/parser/parser_test.go<|end_filename|>
package parser

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"testing"

	"github.com/stretchr/testify/assert"
)

func getRepoRoot() string {
	_, selfFilePath, _, ok := runtime.Caller(0)
	if !ok {
		log.Fatalf("can't get caller")
	}

	root, err := filepath.Abs(filepath.Join(filepath.Dir(selfFilePath), ".."))
	if err != nil {
		log.Fatalf("can't get repo root: %s", err)
	}

	return root
}

func getTempDirRoot() string {
	return filepath.Join(getRepoRoot(), "parser", "test")
}

func getTempFileName(rootDir, prefix, suffix string) (*os.File, error) {
	randBytes := make([]byte, 16)
	_, err := rand.Read(randBytes)
	if err != nil {
		return nil, fmt.Errorf("can't generate random bytes: %s", err)
	}

	p := filepath.Join(rootDir, prefix+hex.EncodeToString(randBytes)+suffix)
	return os.Create(p)
}

func getTmpFileForCode(code string) *os.File {
	tmpDir, err := ioutil.TempDir(getTempDirRoot(), "tmptestdir")
	if err != nil {
		log.Fatalf("can't create temp dir: %s", err)
	}

	f, err := getTempFileName(tmpDir, "go-queryset-test", ".go")
	if err != nil {
		log.Fatalf("can't create temp file: %s", err)
	}

	_, err = f.Write([]byte(code))
	if err != nil {
		log.Fatalf("can't write to temp file %q: %s", f.Name(), err)
	}

	return f
}

func removeTempFileAndDir(f *os.File) {
	root := filepath.Dir(f.Name())
	if err := os.RemoveAll(root); err != nil {
		log.Fatalf("can't remove files from root %s: %s", root, err)
	}
}

func TestGetStructNamesInFile(t *testing.T) {
	cases := []struct {
		code                string
		expectedStructNames []string
		errorIsExpected     bool
	}{
		{
			code:            "",
			errorIsExpected: true,
		},
		{
			code: `package p
				type T struct {}`,
			expectedStructNames: []string{"T"},
		},
		{
			code: `package p
				type T1 struct {}
				type T2 struct {}`,
			expectedStructNames: []string{"T1", "T2"},
		},
		{
			code: `package p
				type T1 int
				type T2 struct {}`,
			expectedStructNames: []string{"T2"},
		},
		{
			code: `package p
				var v struct {F int}`,
		},
		{
			code: `package p
				const c = 1`,
		},
	}

	p := Structs{}
	for i, tc := range cases {
		tc := tc // capture range variable
		t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
			t.Parallel()
			f := getTmpFileForCode(tc.code)
			defer removeTempFileAndDir(f)

			res, err := p.getStructNamesInFile(f.Name())
			if tc.errorIsExpected {
				assert.NotNil(t, err)
				return
			}

			assert.Nil(t, err)
			if tc.expectedStructNames == nil {
				tc.expectedStructNames = []string{}
			}
			for _, expStructName := range tc.expectedStructNames {
				decl, ok := res[expStructName]
				assert.True(t, ok, "no struct %s", expStructName)
				assert.NotNil(t, decl)
			}
			assert.Len(t, res, len(tc.expectedStructNames))
		})
	}
}

type structFieldsCase struct {
	code                 string
	expectedStructFields []string
	errorIsExpected      bool
	expectedDoc          []string
	expectedStructsCount int
}

func (tc structFieldsCase) getExpectedtructsCount() int {
	expectedStructsCount := 1
	if tc.expectedStructFields == nil {
		expectedStructsCount = 0
	}
	if tc.expectedStructsCount != 0 {
		expectedStructsCount = tc.expectedStructsCount
	}

	return expectedStructsCount
}

func TestGetStructsInFile(t *testing.T) {
	cases := []structFieldsCase{
		{
			code:            "",
			errorIsExpected: true,
		},
		{
			code: `package p
				type T struct {}`,
		},
		{
			code: `package p
				type T struct {
					F int
				}`,
			expectedStructFields: []string{"F"},
		},
		{
			code: `package p
				type T struct {
					f int
				}`,
		},
		{
			code: `package p
				// doc line 1
				// doc line 2
				type T struct {
					F int
				}`,
			expectedStructFields: []string{"F"},
			expectedDoc:          []string{"// doc line 1", "// doc line 2"},
		},
		{
			code: `package p
				type m struct {
					ID int
				}

				type T struct {
					m
					F int
				}`,
			expectedStructFields: []string{"F", "ID"},
			expectedStructsCount: 2,
		},
		{ // test local reordered embedding
			code: `package p
				type T struct {
					m
					F int
				}
				type m struct {
					ID int
				}`,
			expectedStructFields: []string{"F", "ID"},
			expectedStructsCount: 2,
		},
		{ // test another package imported embedding
			code: `package p
				import "gorm.io/gorm"
				type T struct {
					gorm.Model
					F int
				}`,
			expectedStructFields: []string{"ID", "CreatedAt", "UpdatedAt", "DeletedAt", "F"},
		},
		{
			code: `package p
			type MyType int`,
		},
		{
			code: `package p
				type m struct {
				}

				type T struct {
					m
					F int
				}`,
			expectedStructFields: []string{"F"},
		},
	}

	for i, tc := range cases {
		tc := tc // capture range variable
		t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) {
			t.Parallel()
			testStructFields(t, tc)
		})
	}
}

func testStructFields(t *testing.T, tc structFieldsCase) {
	f := getTmpFileForCode(tc.code)
	defer removeTempFileAndDir(f)

	p := Structs{}
	ret, err := p.ParseFile(context.Background(), f.Name())
	if tc.errorIsExpected {
		assert.NotNil(t, err)
		return
	}

	assert.Nil(t, err)
	assert.NotNil(t, ret)

	assert.Len(t, ret.Structs, tc.getExpectedtructsCount())
	if tc.getExpectedtructsCount() == 0 {
		return
	}

	var typeName string

	for structTypeName := range ret.Structs {
		if structTypeName == "T" {
			typeName = structTypeName
			break
		}
	}
	assert.NotNil(t, typeName)

	s := ret.Structs[typeName]
	fieldNames := []string{}
	for _, field := range s.Fields {
		assert.NotEmpty(t, field.Name)
		fieldNames = append(fieldNames, field.name)
	}
	assert.Len(t, fieldNames, len(tc.expectedStructFields))

	if tc.expectedDoc != nil {
		docLines := []string{}
		assert.NotNil(t, s.Doc)
		for _, docLine := range s.Doc.List {
			docLines = append(docLines, docLine.Text)
		}
		assert.Equal(t, tc.expectedDoc, docLines)
	}
}


<|start_filename|>node/driver/serve_device.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package driver

import (
	"context"
	"net"

	"github.com/pairmesh/pairmesh/constant"
	"github.com/pairmesh/pairmesh/pkg/logutil"
	"go.uber.org/zap"
)

func parseDst(b []byte) net.IP {
	if len(b) < 20 {
		return nil
	}
	return net.IPv4(b[16], b[17], b[18], b[19])
}

func (d *NodeDriver) serveDevRead(ctx context.Context) {
	defer d.wg.Done()

	npnp := net.IPv4(239, 255, 255, 250)

	buffer := make([]byte, constant.MaxBufferSize)
	for {
		select {
		case <-ctx.Done():
			zap.L().Info("Serve virtual device read goroutine stopped")
			return

		default:
			c, err := d.device.Read(buffer)
			if err != nil {
				continue
			}

			if !d.enable.Load() {
				continue
			}

			dst := parseDst(buffer[:c])
			if dst == nil {
				zap.L().Warn("Parse IPv4 header failed", zap.ByteString("data", buffer[:c]))
				continue
			}

			if dst.Equal(npnp) {
				continue
			}

			if logutil.IsEnableDevice() {
				zap.L().Debug("Read packet from device", zap.Stringer("to", dst))
			}

			// TODO: support broadcast
			destination := dst.String()
			t := d.mm.Tunnel(destination)
			if t == nil {
				continue
			}

			dataCopy := make([]byte, c)
			copy(dataCopy, buffer[:c])

			// Write pipeline back if the destination is the current virtual address (loopback)
			if destination == d.credential.address {
				d.chDevWrite <- dataCopy
				continue
			}

			t.Write(dataCopy)
		}
	}
}

func (d *NodeDriver) serveDevWrite(ctx context.Context) {
	defer d.wg.Done()

	for {
		select {
		case <-ctx.Done():
			zap.L().Info("Serve virtual device write goroutine stopped")
			return

		case data := <-d.chDevWrite:
			if !d.enable.Load() {
				continue
			}

			if logutil.IsEnableDevice() {
				dst := parseDst(data)
				if dst == nil {
					zap.L().Warn("Parse IPv4 header failed", zap.ByteString("data", data))
					continue
				}
				zap.L().Debug("Writing packet into device", zap.Stringer("to", dst))
			}

			_, err := d.device.Write(data)
			if err != nil {
				zap.L().Error("Write data into virtual device failed", zap.Error(err))
			}
		}
	}
}


<|start_filename|>node/entry/exchange.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package entry

import (
	"github.com/pairmesh/pairmesh/node/api"
	"github.com/pairmesh/pairmesh/node/config"
	"go.uber.org/zap"
)

func exchangeAuthKeyIfNeed(apiClient *api.Client, config *config.Config) error {
	if !config.IsAuthKey() {
		return nil
	}

	resp, err := apiClient.KeyExchange()
	if err != nil {
		return err
	}

	err = config.SetJWTToken(resp.AccessToken)
	if err != nil {
		return err
	}

	apiClient.SetToken(config.Token)

	zap.L().Info("Exchange auth key finished")

	return nil
}


<|start_filename|>portal/db/interface.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package db

import (
	"database/sql"
	"errors"
	"fmt"

	"github.com/pairmesh/pairmesh/portal/config"
	"github.com/pairmesh/pairmesh/portal/db/models"
	"go.uber.org/atomic"
	"go.uber.org/zap"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

var initialized = atomic.Bool{}
var globalDB *gorm.DB

// Initialize initialize the database
func Initialize(cfg *config.MySQL) error {
	if initialized.Swap(true) {
		return errors.New("initialize twice")
	}

	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=true&loc=Local", cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DB)
	db, err := gorm.Open(mysql.New(mysql.Config{DSN: dsn}), &gorm.Config{Logger: &Logger{}})
	if err != nil {
		return err
	}

	allTables := []interface{}{
		&models.User{},
		&models.AuthKey{},
		&models.NetworkUser{},
		&models.Invitation{},
		&models.Network{},
		&models.Device{},
		&models.RelayServer{},
		&models.GithubUser{},
		&models.WechatUser{},
	}

	// Create table if not exists
	err = db.AutoMigrate(allTables...)
	if err != nil {
		return err
	}

	db.Logger.LogMode(logger.Info)

	// The global database instance.
	globalDB = db

	zap.L().Info("Preflight the database successfully",
		zap.String("host", cfg.Host),
		zap.Int("port", cfg.Port),
		zap.String("user", cfg.User),
		zap.String("db", cfg.DB))

	return nil
}

// Tx start a transaction as a block, return error will rollback, otherwise to commit.
func Tx(fc func(tx *gorm.DB) error, opts ...*sql.TxOptions) error {
	return globalDB.Transaction(fc, opts...)
}

// Create inserts a record into the database
func Create(bean interface{}) error {
	return globalDB.Transaction(func(tx *gorm.DB) error {
		tx.Create(bean)
		return tx.Error
	})
}


<|start_filename|>portal/api/server.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import (
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"fmt"
	"net/http"
	"sync"
	"time"

	"github.com/NYTimes/gziphandler"
	"github.com/gorilla/mux"
	"github.com/pairmesh/pairmesh/constant"
	"github.com/pairmesh/pairmesh/portal/db"
	"github.com/pairmesh/pairmesh/portal/db/models"
	"github.com/pingcap/fn"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

const credentialLease = time.Hour

type (
	publicKey struct {
		// BASE64 representation of the public key, which is used to cache the
		// base64 encoded raw data to avoid encoding every relayServer keepalive
		// request.
		base64 string
		raw    *rsa.PublicKey
	}

	relayServers struct {
		byAddr sync.Map
		byID   sync.Map
	}

	// server represents the HTTP server which serves for the current PairMesh portal.
	server struct {
		// relayAuthKey is used to authenticate the relayServer servers requests.
		relayAuthKey string

		// privateKey is used to sign the credential which is used to identify
		// the node hold the IP address of specified network id.
		// TODO: private key rotate
		privateKey *rsa.PrivateKey
		publicKey  publicKey

		// ServerID -> models.RelayServer
		relayServers relayServers
	}
)

// newServer returns a new gateway server instance and the gateway server is
// used to handle the HTTP requests/UDP packets and store the peer information.
func newServer(relayAuthKey string, privateKey *rsa.PrivateKey) *server {
	srv := &server{
		relayAuthKey: relayAuthKey,
		privateKey:   privateKey,
		publicKey: publicKey{
			base64: base64.RawStdEncoding.EncodeToString(x509.MarshalPKCS1PublicKey(&privateKey.PublicKey)),
			raw:    &privateKey.PublicKey,
		},
	}
	return srv

}

// preload the data that persistent in the database.
func (s *server) preload() error {
	// Load the relay servers from database.
	zap.L().Info("Preload the relay servers from database")

	var relayServers []models.RelayServer
	err := db.Tx(func(tx *gorm.DB) error {
		return models.NewRelayServerQuerySet(tx).All(&relayServers)
	})
	if err != nil {
		zap.L().Error("Preload relay servers node is failed", zap.Error(err))
		return err
	}

	for _, r := range relayServers {
		s.relayServers.byID.Store(r.ID, &r)
		s.relayServers.byAddr.Store(fmt.Sprintf("%s:%d", r.Host, r.Port), &r)
	}

	return nil
}

// routers returns the route which routes all HTTP API requests
func route(server *server, ssoSrv *ssoServer) http.Handler {
	// Preflight the HTTP service and register all APIs
	router := mux.NewRouter()

	// All APIs for SSO Login/out: `/api/v1/login`
	router.Handle("/api/v1/version/check", fn.Wrap(server.VersionCheck)).Methods(http.MethodGet)
	router.Handle("/api/v1/login/sso-methods", fn.Wrap(ssoSrv.SSOMethods)).Methods(http.MethodGet)
	router.Handle("/api/v1/login/auth/callback/github", fn.Wrap(ssoSrv.GithubAuthCallback)).Methods(http.MethodPost)
	router.Handle(constant.URILogout, http.HandlerFunc(ssoSrv.Logout)).Methods(http.MethodGet)

	// All HTTP APIs requested by the relayServer servers
	relayAPI := fn.NewGroup().Plugin(relayAuthKeyValidator(server.relayAuthKey))
	router.Handle(constant.URIRelay, relayAPI.Wrap(server.RelayKeepalive)).Methods(http.MethodPost)

	// All HTTP APIs requested by the PairMesh peers
	peerAPI := fn.NewGroup().Plugin(peerTokenValidator)
	router.Handle(constant.URIDevicePeerGraph, peerAPI.Wrap(server.PeerGraph)).Methods(http.MethodGet)
	router.Handle(constant.URIDevicePreflight, peerAPI.Wrap(server.Preflight)).Methods(http.MethodPost)
	router.Handle(constant.URIRenewCredential, peerAPI.Wrap(server.RenewCredential)).Methods(http.MethodPost)
	router.Handle(constant.URLKeyExchange, peerAPI.Wrap(server.ExchangeKey)).Methods(http.MethodPost)

	// All HTTP APIs authed by jwt or auth key
	httpAPI := fn.NewGroup().Plugin(tokenValidator)
	router.Handle("/api/v1/settings/user/profile", httpAPI.Wrap(server.UserProfileSetting)).Methods(http.MethodPut)
	router.Handle("/api/v1/keys", httpAPI.Wrap(server.KeyList)).Methods(http.MethodGet)
	router.Handle("/api/v1/key", httpAPI.Wrap(server.CreateKey)).Methods(http.MethodPost)
	router.Handle("/api/v1/key/{key_id}", httpAPI.Wrap(server.ChangeKey)).Methods(http.MethodPut)
	router.Handle("/api/v1/key/{key_id}", httpAPI.Wrap(server.DeleteKey)).Methods(http.MethodDelete)
	router.Handle("/api/v1/user/profile", httpAPI.Wrap(server.UserProfile)).Methods(http.MethodGet)
	router.Handle("/api/v1/user/{user_id}/devices", httpAPI.Wrap(server.UserDeviceList)).Methods(http.MethodGet)
	router.Handle("/api/v1/devices", httpAPI.Wrap(server.DeviceList)).Methods(http.MethodGet)
	router.Handle("/api/v1/device/{device_id}", httpAPI.Wrap(server.DeviceUpdate)).Methods(http.MethodPut)
	router.Handle("/api/v1/networks", httpAPI.Wrap(server.NetworkList)).Methods(http.MethodGet)
	router.Handle("/api/v1/network", httpAPI.Wrap(server.CreateNetwork)).Methods(http.MethodPost)
	router.Handle("/api/v1/network/{network_id}", httpAPI.Wrap(server.UpdateNetwork)).Methods(http.MethodPut)
	router.Handle("/api/v1/network/{network_id}", httpAPI.Wrap(server.DeleteNetwork)).Methods(http.MethodDelete)
	router.Handle("/api/v1/network/{network_id}/members", httpAPI.Wrap(server.NetworkMembers)).Methods(http.MethodGet)
	router.Handle("/api/v1/network/{network_id}/member/invite", httpAPI.Wrap(server.InviteMember)).Methods(http.MethodPost)
	router.Handle("/api/v1/network/{network_id}/member/{user_id}", httpAPI.Wrap(server.DeleteNetworkUser)).Methods(http.MethodDelete)
	router.Handle("/api/v1/network/{network_id}/member/{user_id}/role", httpAPI.Wrap(server.ChangeNetworkMemberRole)).Methods(http.MethodPut)
	router.Handle("/api/v1/invitations", httpAPI.Wrap(server.Invitations)).Methods(http.MethodGet)
	router.Handle("/api/v1/invitation/{invitation_id}", httpAPI.Wrap(server.HandleInvitation)).Methods(http.MethodPut)

	return gziphandler.GzipHandler(router)
}


<|start_filename|>internal/ledis/ledis.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ledis

import (
	"context"
	"errors"
	"fmt"
	"time"

	lediscfg "github.com/ledisdb/ledisdb/config"
	"github.com/ledisdb/ledisdb/ledis"
	"go.uber.org/zap"
)

// ErrIllegalParameter represents the input parameter(s) is illegal
var ErrIllegalParameter = errors.New("illegal parameter")

var shared *ledisStore

type ledisStore struct {
	l *ledis.DB
}

// Initialize initializes the ledis cache.
func Initialize(dataPath string) error {
	cfg := lediscfg.NewConfigDefault()
	cfg.DataDir = dataPath
	l, err := ledis.Open(cfg)
	if err != nil {
		return err
	}

	db, err := l.Select(0)
	if err != nil {
		return err
	}

	shared = &ledisStore{db}

	zap.L().Info("initialize the ledis successfully")
	return nil
}

func (r *ledisStore) Set(_ context.Context, key string, value interface{}, expiration time.Duration) error {
	return r.l.SetEX([]byte(key), int64(expiration.Seconds()), []byte(fmt.Sprintf("%v", value)))
}
func (r *ledisStore) Del(_ context.Context, keys ...string) error {
	var kb [][]byte
	for _, k := range keys {
		kb = append(kb, []byte(k))
	}
	_, err := r.l.Del(kb...)
	return err
}

func (r *ledisStore) Get(_ context.Context, key string) (interface{}, error) {
	res, err := r.l.Get([]byte(key))
	return string(res), err
}

// Shared represents the global redis object
func Shared() *ledisStore {
	return shared
}


<|start_filename|>portal/webui/src/api/service.js<|end_filename|>
// Copyright 2022 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import axios from 'axios'

const service = axios.create({
    timeout: 5000,
    responseType: 'json',
    headers: {
        "Content-Type": "application/json;charset=utf-8"
    }
})

service.interceptors.request.use(
    config => {
        config.headers['Authorization'] = 'Bearer ' + localStorage.getItem('accessToken')
        config.data = JSON.stringify(config.data);
        return config;
    },
    error => {
        return Promise.reject(error);
    }
)

service.interceptors.response.use(
    response => {
        if (response.status === 200) {
            return Promise.resolve(response);
        } else {
            return Promise.reject(response);
        }
    },
    error => {
        if (error.response.status) {
            switch (error.response.status) {
                case 401:
                case 403:
                    window.location.href = '/login';
                    break;

                default:
                    return Promise.reject(error.response);
            }
            return Promise.reject(error.response);
        }
    },
);

export default service;

<|start_filename|>node/mesh/tunnel/endpoint.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tunnel

import (
	"context"
	"net"
	"time"

	"github.com/pairmesh/pairmesh/constant"
	"github.com/pairmesh/pairmesh/pkg/logutil"

	"go.uber.org/atomic"
	"go.uber.org/zap"
)

// Endpoint represents the record of discovering peerinfo via message.PacketType_Discovery.
type Endpoint struct {
	served   atomic.Bool
	address  string
	udpConn  *net.UDPConn
	latency  time.Duration
	lastSeen time.Time
	callback UDPPacketCallback
	cancelFn context.CancelFunc
	chWrite  chan []byte
}

func newEndpoint(udpConn *net.UDPConn, latency time.Duration, lastSeen time.Time, callback UDPPacketCallback) *Endpoint {
	return &Endpoint{
		address:  udpConn.RemoteAddr().String(),
		udpConn:  udpConn,
		latency:  latency,
		lastSeen: lastSeen,
		callback: callback,
		chWrite:  make(chan []byte, 128),
	}
}

func (c *Endpoint) Write(data []byte) {
	c.chWrite <- data
}

func (c *Endpoint) serve() {
	if c.served.Swap(true) {
		return
	}

	ctx, cancel := context.WithCancel(context.Background())
	c.cancelFn = cancel

	go c.serveRead(ctx)
	go c.serveWrite(ctx)
}

func (c *Endpoint) serveRead(ctx context.Context) {
	defer c.udpConn.Close()

	buffer := make([]byte, constant.MaxBufferSize)
	for {
		select {
		case <-ctx.Done():
			zap.L().Info("Serve endpoint connection read goroutine stopped", zap.String("address", c.address))
			return

		default:
			n, err := c.udpConn.Read(buffer)
			if err != nil {
				continue
			}

			if logutil.IsEnablePeer() {
				zap.L().Debug("Read packet from peer", zap.String("from", c.address))
			}

			c.callback.OnUDPPacket(c.udpConn, buffer[:n])
		}
	}
}

func (c *Endpoint) serveWrite(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			zap.L().Info("Serve endpoint connection write goroutine stopped", zap.String("address", c.address))
			return

		case data := <-c.chWrite:
			if logutil.IsEnablePeer() {
				zap.L().Debug("Write packet in peer", zap.String("to", c.address))
			}

			_, err := c.udpConn.Write(data)
			if err != nil {
				zap.L().Error("Write data to peer failed", zap.Error(err))
			}
		}
	}
}


<|start_filename|>internal/messagebox/cocoa/dlg_darwin.go<|end_filename|>
package cocoa

// #cgo darwin LDFLAGS: -framework Cocoa
// #include <stdlib.h>
// #include <sys/syslimits.h>
// #include "dlg.h"
import "C"

import (
	"unsafe"
)

type AlertParams struct {
	p C.AlertDlgParams
}

func mkAlertParams(title, content string, style C.AlertStyle) *AlertParams {
	a := AlertParams{C.AlertDlgParams{title: C.CString(title), msg: C.CString(content), style: style}}
	return &a
}

func (a *AlertParams) run() C.DlgResult {
	return C.alertDlg(&a.p)
}

func (a *AlertParams) free() {
	C.free(unsafe.Pointer(a.p.msg))
	C.free(unsafe.Pointer(a.p.title))
}

func Confirm(title, content string) bool {
	a := mkAlertParams(title, content, C.MSG_YESNO)
	defer a.free()
	return a.run() == C.DLG_OK
}

func Info(title, content string) {
	a := mkAlertParams(title, content, C.MSG_INFO)
	defer a.free()
	a.run()
}

func Error(title, content string) {
	a := mkAlertParams(title, content, C.MSG_ERROR)
	defer a.free()
	a.run()
}


<|start_filename|>node/device/tun/tun_darwin_legacy.go<|end_filename|>
//go:build darwin && !go1.11
// +build darwin,!go1.11

// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tun

func setNonBlock(fd int) error {
	// There's a but pre-go1.11 that causes 'resource temporarily unavailable'
	// error in non-blocking mode. So just skip it here. Close() won't be able
	// to unblock a pending read, but that's better than being broken.
	return nil
}


<|start_filename|>message/packet.pb.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// 	protoc-gen-go v1.26.0
// 	protoc        v3.17.3
// source: packet.proto

package message

import (
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
	reflect "reflect"
	sync "sync"
)

const (
	// Verify that this generated code is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
	// Verify that runtime/protoimpl is sufficiently up-to-date.
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)

type PacketType int32

const (
	// Handshake packet is use to handshake with the relay server. The handshake
	// message should be the first message between relay server and peer client.
	// The message is used to exchange the DH key and generate the shared key for
	// the subsequence messages.
	//
	// The subsequence messages will not be handled by the relay server if the
	// handshake has not completed.
	PacketType_Handshake    PacketType = 0 // DIRECTION: peer -> relay server (TCP)
	PacketType_HandshakeAck PacketType = 1 // DIRECTION: relay server -> peer (TCP)
	// Probe packet is used to probe if peers connected to the relay server.
	PacketType_ProbeRequest  PacketType = 2 // DIRECTION: peer -> relay server (TCP)
	PacketType_ProbeResponse PacketType = 3 // DIRECTION: relay server -> peer (TCP)
	// Heartbeat packet is used to keep alive between PairMesh node and relay servers
	PacketType_Heartbeat PacketType = 4 // DIRECTION: peer <-> relay server
	// SyncPeer packet is used to synchronize the peer information between PairMesh nodes.
	PacketType_SyncPeer PacketType = 5 // DIRECTION: peer <-> relay server <-> peer (TCP)
	// Forward represents the relay message which is forwarded by the relay server.
	PacketType_Forward PacketType = 6 // DIRECTION: peer -> relay server -> peer (TCP)
	// PEER MESSAGE: UDP packet between peers.
	PacketType_Discovery PacketType = 7 // DIRECTION: peer -> peer (UDP)
	// PEER MESSAGE: UDP packet the raw IP fragment red from virtual network device.
	PacketType_Fragment          PacketType = 8 // DIRECTION: peer -> peer (UDP)
	PacketType__UnitTestRequest  PacketType = 99
	PacketType__UnitTestResponse PacketType = 100
)

// Enum value maps for PacketType.
var (
	PacketType_name = map[int32]string{
		0:   "Handshake",
		1:   "HandshakeAck",
		2:   "ProbeRequest",
		3:   "ProbeResponse",
		4:   "Heartbeat",
		5:   "SyncPeer",
		6:   "Forward",
		7:   "Discovery",
		8:   "Fragment",
		99:  "_UnitTestRequest",
		100: "_UnitTestResponse",
	}
	PacketType_value = map[string]int32{
		"Handshake":         0,
		"HandshakeAck":      1,
		"ProbeRequest":      2,
		"ProbeResponse":     3,
		"Heartbeat":         4,
		"SyncPeer":          5,
		"Forward":           6,
		"Discovery":         7,
		"Fragment":          8,
		"_UnitTestRequest":  99,
		"_UnitTestResponse": 100,
	}
)

func (x PacketType) Enum() *PacketType {
	p := new(PacketType)
	*p = x
	return p
}

func (x PacketType) String() string {
	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}

func (PacketType) Descriptor() protoreflect.EnumDescriptor {
	return file_packet_proto_enumTypes[0].Descriptor()
}

func (PacketType) Type() protoreflect.EnumType {
	return &file_packet_proto_enumTypes[0]
}

func (x PacketType) Number() protoreflect.EnumNumber {
	return protoreflect.EnumNumber(x)
}

// Deprecated: Use PacketType.Descriptor instead.
func (PacketType) EnumDescriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{0}
}

type PacketSyncPeer_Purpose int32

const (
	PacketSyncPeer_Undefined PacketSyncPeer_Purpose = 0
	// Catch up is used to synchronize the peer endpoints information between peers.
	// All new startup device will retrieve the peers list and send `PacketSyncEndpoints`
	// with the `Catchup` purpose message for all online devices.
	PacketSyncPeer_Catchup    PacketSyncPeer_Purpose = 1
	PacketSyncPeer_CatchupAck PacketSyncPeer_Purpose = 2
	// All message communication via relay server by default and the `PairRequest/PairResponse`
	// purpose will try to establish P2P connection between peers.
	PacketSyncPeer_PairRequest      PacketSyncPeer_Purpose = 3
	PacketSyncPeer_PairResponse     PacketSyncPeer_Purpose = 4
	PacketSyncPeer_EndpointsChanged PacketSyncPeer_Purpose = 5
)

// Enum value maps for PacketSyncPeer_Purpose.
var (
	PacketSyncPeer_Purpose_name = map[int32]string{
		0: "Undefined",
		1: "Catchup",
		2: "CatchupAck",
		3: "PairRequest",
		4: "PairResponse",
		5: "EndpointsChanged",
	}
	PacketSyncPeer_Purpose_value = map[string]int32{
		"Undefined":        0,
		"Catchup":          1,
		"CatchupAck":       2,
		"PairRequest":      3,
		"PairResponse":     4,
		"EndpointsChanged": 5,
	}
)

func (x PacketSyncPeer_Purpose) Enum() *PacketSyncPeer_Purpose {
	p := new(PacketSyncPeer_Purpose)
	*p = x
	return p
}

func (x PacketSyncPeer_Purpose) String() string {
	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}

func (PacketSyncPeer_Purpose) Descriptor() protoreflect.EnumDescriptor {
	return file_packet_proto_enumTypes[1].Descriptor()
}

func (PacketSyncPeer_Purpose) Type() protoreflect.EnumType {
	return &file_packet_proto_enumTypes[1]
}

func (x PacketSyncPeer_Purpose) Number() protoreflect.EnumNumber {
	return protoreflect.EnumNumber(x)
}

// Deprecated: Use PacketSyncPeer_Purpose.Descriptor instead.
func (PacketSyncPeer_Purpose) EnumDescriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{5, 0}
}

type PacketHandshake struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	// Credentials encrypted by the shared key. The shared key generated by the noise protocol.
	// Workflow:
	// 1. Client fetch its primary server information from portal service.
	// 2. Client handshake with relay server and put the credentials into HandshakeMessage.
	Message []byte `protobuf:"bytes,1,opt,name=Message,proto3" json:"Message,omitempty"`
	// IsPrimary indicates whether is the destination relay server the primary server of client.
	IsPrimary bool `protobuf:"varint,2,opt,name=IsPrimary,proto3" json:"IsPrimary,omitempty"`
}

func (x *PacketHandshake) Reset() {
	*x = PacketHandshake{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[0]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketHandshake) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketHandshake) ProtoMessage() {}

func (x *PacketHandshake) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[0]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketHandshake.ProtoReflect.Descriptor instead.
func (*PacketHandshake) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{0}
}

func (x *PacketHandshake) GetMessage() []byte {
	if x != nil {
		return x.Message
	}
	return nil
}

func (x *PacketHandshake) GetIsPrimary() bool {
	if x != nil {
		return x.IsPrimary
	}
	return false
}

type PacketHandshakeAck struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Message []byte `protobuf:"bytes,1,opt,name=Message,proto3" json:"Message,omitempty"`
}

func (x *PacketHandshakeAck) Reset() {
	*x = PacketHandshakeAck{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[1]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketHandshakeAck) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketHandshakeAck) ProtoMessage() {}

func (x *PacketHandshakeAck) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[1]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketHandshakeAck.ProtoReflect.Descriptor instead.
func (*PacketHandshakeAck) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{1}
}

func (x *PacketHandshakeAck) GetMessage() []byte {
	if x != nil {
		return x.Message
	}
	return nil
}

type PacketHeartbeat struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Timestamp int64 `protobuf:"varint,1,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"`
}

func (x *PacketHeartbeat) Reset() {
	*x = PacketHeartbeat{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[2]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketHeartbeat) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketHeartbeat) ProtoMessage() {}

func (x *PacketHeartbeat) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[2]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketHeartbeat.ProtoReflect.Descriptor instead.
func (*PacketHeartbeat) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{2}
}

func (x *PacketHeartbeat) GetTimestamp() int64 {
	if x != nil {
		return x.Timestamp
	}
	return 0
}

type PacketProbeRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Peers []uint64 `protobuf:"varint,1,rep,packed,name=Peers,proto3" json:"Peers,omitempty"`
}

func (x *PacketProbeRequest) Reset() {
	*x = PacketProbeRequest{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[3]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketProbeRequest) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketProbeRequest) ProtoMessage() {}

func (x *PacketProbeRequest) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[3]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketProbeRequest.ProtoReflect.Descriptor instead.
func (*PacketProbeRequest) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{3}
}

func (x *PacketProbeRequest) GetPeers() []uint64 {
	if x != nil {
		return x.Peers
	}
	return nil
}

type PacketProbeResponse struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	OnlinePeers  []uint64 `protobuf:"varint,1,rep,packed,name=OnlinePeers,proto3" json:"OnlinePeers,omitempty"`
	OfflinePeers []uint64 `protobuf:"varint,2,rep,packed,name=OfflinePeers,proto3" json:"OfflinePeers,omitempty"`
}

func (x *PacketProbeResponse) Reset() {
	*x = PacketProbeResponse{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[4]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketProbeResponse) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketProbeResponse) ProtoMessage() {}

func (x *PacketProbeResponse) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[4]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketProbeResponse.ProtoReflect.Descriptor instead.
func (*PacketProbeResponse) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{4}
}

func (x *PacketProbeResponse) GetOnlinePeers() []uint64 {
	if x != nil {
		return x.OnlinePeers
	}
	return nil
}

func (x *PacketProbeResponse) GetOfflinePeers() []uint64 {
	if x != nil {
		return x.OfflinePeers
	}
	return nil
}

type PacketSyncPeer struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	DstPeerID uint64                 `protobuf:"varint,1,opt,name=DstPeerID,proto3" json:"DstPeerID,omitempty"`
	Purpose   PacketSyncPeer_Purpose `protobuf:"varint,2,opt,name=purpose,proto3,enum=PacketSyncPeer_Purpose" json:"purpose,omitempty"`
	// Only be assigned a value if the purpose is
	Peer *PacketSyncPeer_PeerInfo `protobuf:"bytes,3,opt,name=Peer,proto3" json:"Peer,omitempty"`
	// Only be assigned a value if the purpose is `PairRequest/PairResponse/EndpointsChanged`
	Endpoints []string `protobuf:"bytes,4,rep,name=endpoints,proto3" json:"endpoints,omitempty"`
}

func (x *PacketSyncPeer) Reset() {
	*x = PacketSyncPeer{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[5]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketSyncPeer) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketSyncPeer) ProtoMessage() {}

func (x *PacketSyncPeer) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[5]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketSyncPeer.ProtoReflect.Descriptor instead.
func (*PacketSyncPeer) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{5}
}

func (x *PacketSyncPeer) GetDstPeerID() uint64 {
	if x != nil {
		return x.DstPeerID
	}
	return 0
}

func (x *PacketSyncPeer) GetPurpose() PacketSyncPeer_Purpose {
	if x != nil {
		return x.Purpose
	}
	return PacketSyncPeer_Undefined
}

func (x *PacketSyncPeer) GetPeer() *PacketSyncPeer_PeerInfo {
	if x != nil {
		return x.Peer
	}
	return nil
}

func (x *PacketSyncPeer) GetEndpoints() []string {
	if x != nil {
		return x.Endpoints
	}
	return nil
}

type PacketForward struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	SrcPeerID uint64 `protobuf:"varint,1,opt,name=SrcPeerID,proto3" json:"SrcPeerID,omitempty"`
	DstPeerID uint64 `protobuf:"varint,2,opt,name=DstPeerID,proto3" json:"DstPeerID,omitempty"`
	Nonce     uint32 `protobuf:"varint,3,opt,name=Nonce,proto3" json:"Nonce,omitempty"`
	Fragment  []byte `protobuf:"bytes,4,opt,name=Fragment,proto3" json:"Fragment,omitempty"`
}

func (x *PacketForward) Reset() {
	*x = PacketForward{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[6]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketForward) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketForward) ProtoMessage() {}

func (x *PacketForward) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[6]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketForward.ProtoReflect.Descriptor instead.
func (*PacketForward) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{6}
}

func (x *PacketForward) GetSrcPeerID() uint64 {
	if x != nil {
		return x.SrcPeerID
	}
	return 0
}

func (x *PacketForward) GetDstPeerID() uint64 {
	if x != nil {
		return x.DstPeerID
	}
	return 0
}

func (x *PacketForward) GetNonce() uint32 {
	if x != nil {
		return x.Nonce
	}
	return 0
}

func (x *PacketForward) GetFragment() []byte {
	if x != nil {
		return x.Fragment
	}
	return nil
}

type PacketDiscovery struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	SenderPeerID uint64 `protobuf:"varint,1,opt,name=SenderPeerID,proto3" json:"SenderPeerID,omitempty"`
	// Timestamp is used to metric the latency between two peers.
	Timestamp int64 `protobuf:"varint,2,opt,name=Timestamp,proto3" json:"Timestamp,omitempty"`
}

func (x *PacketDiscovery) Reset() {
	*x = PacketDiscovery{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[7]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketDiscovery) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketDiscovery) ProtoMessage() {}

func (x *PacketDiscovery) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[7]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketDiscovery.ProtoReflect.Descriptor instead.
func (*PacketDiscovery) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{7}
}

func (x *PacketDiscovery) GetSenderPeerID() uint64 {
	if x != nil {
		return x.SenderPeerID
	}
	return 0
}

func (x *PacketDiscovery) GetTimestamp() int64 {
	if x != nil {
		return x.Timestamp
	}
	return 0
}

type P_UnitTestRequest struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Field string `protobuf:"bytes,1,opt,name=Field,proto3" json:"Field,omitempty"`
}

func (x *P_UnitTestRequest) Reset() {
	*x = P_UnitTestRequest{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[8]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *P_UnitTestRequest) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*P_UnitTestRequest) ProtoMessage() {}

func (x *P_UnitTestRequest) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[8]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use P_UnitTestRequest.ProtoReflect.Descriptor instead.
func (*P_UnitTestRequest) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{8}
}

func (x *P_UnitTestRequest) GetField() string {
	if x != nil {
		return x.Field
	}
	return ""
}

type P_UnitTestResponse struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Field string `protobuf:"bytes,1,opt,name=Field,proto3" json:"Field,omitempty"`
}

func (x *P_UnitTestResponse) Reset() {
	*x = P_UnitTestResponse{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[9]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *P_UnitTestResponse) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*P_UnitTestResponse) ProtoMessage() {}

func (x *P_UnitTestResponse) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[9]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use P_UnitTestResponse.ProtoReflect.Descriptor instead.
func (*P_UnitTestResponse) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{9}
}

func (x *P_UnitTestResponse) GetField() string {
	if x != nil {
		return x.Field
	}
	return ""
}

type PacketSyncPeer_Network struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"`
	ID   uint64 `protobuf:"varint,2,opt,name=ID,proto3" json:"ID,omitempty"`
}

func (x *PacketSyncPeer_Network) Reset() {
	*x = PacketSyncPeer_Network{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[10]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketSyncPeer_Network) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketSyncPeer_Network) ProtoMessage() {}

func (x *PacketSyncPeer_Network) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[10]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketSyncPeer_Network.ProtoReflect.Descriptor instead.
func (*PacketSyncPeer_Network) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{5, 0}
}

func (x *PacketSyncPeer_Network) GetName() string {
	if x != nil {
		return x.Name
	}
	return ""
}

func (x *PacketSyncPeer_Network) GetID() uint64 {
	if x != nil {
		return x.ID
	}
	return 0
}

type PacketSyncPeer_RelayServer struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	ID        uint64 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"`
	Name      string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"`
	Region    string `protobuf:"bytes,3,opt,name=Region,proto3" json:"Region,omitempty"`
	Host      string `protobuf:"bytes,4,opt,name=Host,proto3" json:"Host,omitempty"`
	Port      uint32 `protobuf:"varint,5,opt,name=Port,proto3" json:"Port,omitempty"`
	PublicKey string `protobuf:"bytes,6,opt,name=PublicKey,proto3" json:"PublicKey,omitempty"`
}

func (x *PacketSyncPeer_RelayServer) Reset() {
	*x = PacketSyncPeer_RelayServer{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[11]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketSyncPeer_RelayServer) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketSyncPeer_RelayServer) ProtoMessage() {}

func (x *PacketSyncPeer_RelayServer) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[11]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketSyncPeer_RelayServer.ProtoReflect.Descriptor instead.
func (*PacketSyncPeer_RelayServer) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{5, 1}
}

func (x *PacketSyncPeer_RelayServer) GetID() uint64 {
	if x != nil {
		return x.ID
	}
	return 0
}

func (x *PacketSyncPeer_RelayServer) GetName() string {
	if x != nil {
		return x.Name
	}
	return ""
}

func (x *PacketSyncPeer_RelayServer) GetRegion() string {
	if x != nil {
		return x.Region
	}
	return ""
}

func (x *PacketSyncPeer_RelayServer) GetHost() string {
	if x != nil {
		return x.Host
	}
	return ""
}

func (x *PacketSyncPeer_RelayServer) GetPort() uint32 {
	if x != nil {
		return x.Port
	}
	return 0
}

func (x *PacketSyncPeer_RelayServer) GetPublicKey() string {
	if x != nil {
		return x.PublicKey
	}
	return ""
}

type PacketSyncPeer_PeerInfo struct {
	state         protoimpl.MessageState
	sizeCache     protoimpl.SizeCache
	unknownFields protoimpl.UnknownFields

	PeerID        uint64                      `protobuf:"varint,1,opt,name=PeerID,proto3" json:"PeerID,omitempty"`
	UserID        uint64                      `protobuf:"varint,2,opt,name=UserID,proto3" json:"UserID,omitempty"`
	Name          string                      `protobuf:"bytes,3,opt,name=Name,proto3" json:"Name,omitempty"`
	IPv4          string                      `protobuf:"bytes,4,opt,name=IPv4,proto3" json:"IPv4,omitempty"`
	PublicKey     []byte                      `protobuf:"bytes,5,opt,name=PublicKey,proto3" json:"PublicKey,omitempty"`
	PrimaryServer *PacketSyncPeer_RelayServer `protobuf:"bytes,6,opt,name=PrimaryServer,proto3" json:"PrimaryServer,omitempty"`
	Networks      []*PacketSyncPeer_Network   `protobuf:"bytes,7,rep,name=Networks,proto3" json:"Networks,omitempty"`
}

func (x *PacketSyncPeer_PeerInfo) Reset() {
	*x = PacketSyncPeer_PeerInfo{}
	if protoimpl.UnsafeEnabled {
		mi := &file_packet_proto_msgTypes[12]
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		ms.StoreMessageInfo(mi)
	}
}

func (x *PacketSyncPeer_PeerInfo) String() string {
	return protoimpl.X.MessageStringOf(x)
}

func (*PacketSyncPeer_PeerInfo) ProtoMessage() {}

func (x *PacketSyncPeer_PeerInfo) ProtoReflect() protoreflect.Message {
	mi := &file_packet_proto_msgTypes[12]
	if protoimpl.UnsafeEnabled && x != nil {
		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
		if ms.LoadMessageInfo() == nil {
			ms.StoreMessageInfo(mi)
		}
		return ms
	}
	return mi.MessageOf(x)
}

// Deprecated: Use PacketSyncPeer_PeerInfo.ProtoReflect.Descriptor instead.
func (*PacketSyncPeer_PeerInfo) Descriptor() ([]byte, []int) {
	return file_packet_proto_rawDescGZIP(), []int{5, 2}
}

func (x *PacketSyncPeer_PeerInfo) GetPeerID() uint64 {
	if x != nil {
		return x.PeerID
	}
	return 0
}

func (x *PacketSyncPeer_PeerInfo) GetUserID() uint64 {
	if x != nil {
		return x.UserID
	}
	return 0
}

func (x *PacketSyncPeer_PeerInfo) GetName() string {
	if x != nil {
		return x.Name
	}
	return ""
}

func (x *PacketSyncPeer_PeerInfo) GetIPv4() string {
	if x != nil {
		return x.IPv4
	}
	return ""
}

func (x *PacketSyncPeer_PeerInfo) GetPublicKey() []byte {
	if x != nil {
		return x.PublicKey
	}
	return nil
}

func (x *PacketSyncPeer_PeerInfo) GetPrimaryServer() *PacketSyncPeer_RelayServer {
	if x != nil {
		return x.PrimaryServer
	}
	return nil
}

func (x *PacketSyncPeer_PeerInfo) GetNetworks() []*PacketSyncPeer_Network {
	if x != nil {
		return x.Networks
	}
	return nil
}

var File_packet_proto protoreflect.FileDescriptor

var file_packet_proto_rawDesc = []byte{
	0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x49,
	0x0a, 0x0f, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b,
	0x65, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
	0x28, 0x0c, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x49,
	0x73, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09,
	0x49, 0x73, 0x50, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x22, 0x2e, 0x0a, 0x12, 0x50, 0x61, 0x63,
	0x6b, 0x65, 0x74, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x41, 0x63, 0x6b, 0x12,
	0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
	0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x2f, 0x0a, 0x0f, 0x50, 0x61, 0x63,
	0x6b, 0x65, 0x74, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x1c, 0x0a, 0x09,
	0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52,
	0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x2a, 0x0a, 0x12, 0x50, 0x61,
	0x63, 0x6b, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
	0x12, 0x14, 0x0a, 0x05, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x04, 0x52,
	0x05, 0x50, 0x65, 0x65, 0x72, 0x73, 0x22, 0x5b, 0x0a, 0x13, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74,
	0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a,
	0x0b, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03,
	0x28, 0x04, 0x52, 0x0b, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12,
	0x22, 0x0a, 0x0c, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18,
	0x02, 0x20, 0x03, 0x28, 0x04, 0x52, 0x0c, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x50, 0x65,
	0x65, 0x72, 0x73, 0x22, 0xd9, 0x05, 0x0a, 0x0e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x79,
	0x6e, 0x63, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x44, 0x73, 0x74, 0x50, 0x65, 0x65,
	0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x44, 0x73, 0x74, 0x50, 0x65,
	0x65, 0x72, 0x49, 0x44, 0x12, 0x31, 0x0a, 0x07, 0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x18,
	0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x79,
	0x6e, 0x63, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x50, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x52, 0x07,
	0x70, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18,
	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x79,
	0x6e, 0x63, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52,
	0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
	0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69,
	0x6e, 0x74, 0x73, 0x1a, 0x2d, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x12,
	0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61,
	0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02,
	0x49, 0x44, 0x1a, 0x8f, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76,
	0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x02,
	0x49, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
	0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e,
	0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x12,
	0x0a, 0x04, 0x48, 0x6f, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x48, 0x6f,
	0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d,
	0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63,
	0x4b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x75, 0x62, 0x6c, 0x69,
	0x63, 0x4b, 0x65, 0x79, 0x1a, 0xf8, 0x01, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x49, 0x6e, 0x66,
	0x6f, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28,
	0x04, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x73, 0x65,
	0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x55, 0x73, 0x65, 0x72, 0x49,
	0x44, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
	0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x49, 0x50, 0x76, 0x34, 0x18, 0x04, 0x20,
	0x01, 0x28, 0x09, 0x52, 0x04, 0x49, 0x50, 0x76, 0x34, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x75, 0x62,
	0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x50, 0x75,
	0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x41, 0x0a, 0x0d, 0x50, 0x72, 0x69, 0x6d, 0x61,
	0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
	0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x50, 0x65, 0x65, 0x72, 0x2e,
	0x52, 0x65, 0x6c, 0x61, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0d, 0x50, 0x72, 0x69,
	0x6d, 0x61, 0x72, 0x79, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x08, 0x4e, 0x65,
	0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x50,
	0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x50, 0x65, 0x65, 0x72, 0x2e, 0x4e, 0x65,
	0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x08, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x22,
	0x6e, 0x0a, 0x07, 0x50, 0x75, 0x72, 0x70, 0x6f, 0x73, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e,
	0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x61, 0x74,
	0x63, 0x68, 0x75, 0x70, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x61, 0x74, 0x63, 0x68, 0x75,
	0x70, 0x41, 0x63, 0x6b, 0x10, 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65,
	0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x61, 0x69, 0x72, 0x52,
	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, 0x04, 0x12, 0x14, 0x0a, 0x10, 0x45, 0x6e, 0x64,
	0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x10, 0x05, 0x22,
	0x7d, 0x0a, 0x0d, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64,
	0x12, 0x1c, 0x0a, 0x09, 0x53, 0x72, 0x63, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20,
	0x01, 0x28, 0x04, 0x52, 0x09, 0x53, 0x72, 0x63, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1c,
	0x0a, 0x09, 0x44, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28,
	0x04, 0x52, 0x09, 0x44, 0x73, 0x74, 0x50, 0x65, 0x65, 0x72, 0x49, 0x44, 0x12, 0x14, 0x0a, 0x05,
	0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x4e, 0x6f, 0x6e,
	0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04,
	0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x53,
	0x0a, 0x0f, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72,
	0x79, 0x12, 0x22, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x65, 0x65, 0x72, 0x49,
	0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x50,
	0x65, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
	0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
	0x61, 0x6d, 0x70, 0x22, 0x29, 0x0a, 0x11, 0x50, 0x5f, 0x55, 0x6e, 0x69, 0x74, 0x54, 0x65, 0x73,
	0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c,
	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x22, 0x2a,
	0x0a, 0x12, 0x50, 0x5f, 0x55, 0x6e, 0x69, 0x74, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70,
	0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20,
	0x01, 0x28, 0x09, 0x52, 0x05, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x2a, 0xc6, 0x01, 0x0a, 0x0a, 0x50,
	0x61, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x48, 0x61, 0x6e,
	0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x48, 0x61, 0x6e, 0x64,
	0x73, 0x68, 0x61, 0x6b, 0x65, 0x41, 0x63, 0x6b, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x72,
	0x6f, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d,
	0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x10, 0x03, 0x12,
	0x0d, 0x0a, 0x09, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x10, 0x04, 0x12, 0x0c,
	0x0a, 0x08, 0x53, 0x79, 0x6e, 0x63, 0x50, 0x65, 0x65, 0x72, 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07,
	0x46, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x44, 0x69, 0x73,
	0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x72, 0x61, 0x67,
	0x6d, 0x65, 0x6e, 0x74, 0x10, 0x08, 0x12, 0x14, 0x0a, 0x10, 0x5f, 0x55, 0x6e, 0x69, 0x74, 0x54,
	0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x10, 0x63, 0x12, 0x15, 0x0a, 0x11,
	0x5f, 0x55, 0x6e, 0x69, 0x74, 0x54, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
	0x65, 0x10, 0x64, 0x42, 0x0f, 0x5a, 0x0d, 0x2e, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x6d, 0x65, 0x73,
	0x73, 0x61, 0x67, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}

var (
	file_packet_proto_rawDescOnce sync.Once
	file_packet_proto_rawDescData = file_packet_proto_rawDesc
)

func file_packet_proto_rawDescGZIP() []byte {
	file_packet_proto_rawDescOnce.Do(func() {
		file_packet_proto_rawDescData = protoimpl.X.CompressGZIP(file_packet_proto_rawDescData)
	})
	return file_packet_proto_rawDescData
}

var file_packet_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_packet_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_packet_proto_goTypes = []interface{}{
	(PacketType)(0),                    // 0: PacketType
	(PacketSyncPeer_Purpose)(0),        // 1: PacketSyncPeer.Purpose
	(*PacketHandshake)(nil),            // 2: PacketHandshake
	(*PacketHandshakeAck)(nil),         // 3: PacketHandshakeAck
	(*PacketHeartbeat)(nil),            // 4: PacketHeartbeat
	(*PacketProbeRequest)(nil),         // 5: PacketProbeRequest
	(*PacketProbeResponse)(nil),        // 6: PacketProbeResponse
	(*PacketSyncPeer)(nil),             // 7: PacketSyncPeer
	(*PacketForward)(nil),              // 8: PacketForward
	(*PacketDiscovery)(nil),            // 9: PacketDiscovery
	(*P_UnitTestRequest)(nil),          // 10: P_UnitTestRequest
	(*P_UnitTestResponse)(nil),         // 11: P_UnitTestResponse
	(*PacketSyncPeer_Network)(nil),     // 12: PacketSyncPeer.Network
	(*PacketSyncPeer_RelayServer)(nil), // 13: PacketSyncPeer.RelayServer
	(*PacketSyncPeer_PeerInfo)(nil),    // 14: PacketSyncPeer.PeerInfo
}
var file_packet_proto_depIdxs = []int32{
	1,  // 0: PacketSyncPeer.purpose:type_name -> PacketSyncPeer.Purpose
	14, // 1: PacketSyncPeer.Peer:type_name -> PacketSyncPeer.PeerInfo
	13, // 2: PacketSyncPeer.PeerInfo.PrimaryServer:type_name -> PacketSyncPeer.RelayServer
	12, // 3: PacketSyncPeer.PeerInfo.Networks:type_name -> PacketSyncPeer.Network
	4,  // [4:4] is the sub-list for method output_type
	4,  // [4:4] is the sub-list for method input_type
	4,  // [4:4] is the sub-list for extension type_name
	4,  // [4:4] is the sub-list for extension extendee
	0,  // [0:4] is the sub-list for field type_name
}

func init() { file_packet_proto_init() }
func file_packet_proto_init() {
	if File_packet_proto != nil {
		return
	}
	if !protoimpl.UnsafeEnabled {
		file_packet_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketHandshake); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketHandshakeAck); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketHeartbeat); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketProbeRequest); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketProbeResponse); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketSyncPeer); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketForward); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketDiscovery); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*P_UnitTestRequest); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*P_UnitTestResponse); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketSyncPeer_Network); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketSyncPeer_RelayServer); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
		file_packet_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
			switch v := v.(*PacketSyncPeer_PeerInfo); i {
			case 0:
				return &v.state
			case 1:
				return &v.sizeCache
			case 2:
				return &v.unknownFields
			default:
				return nil
			}
		}
	}
	type x struct{}
	out := protoimpl.TypeBuilder{
		File: protoimpl.DescBuilder{
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
			RawDescriptor: file_packet_proto_rawDesc,
			NumEnums:      2,
			NumMessages:   13,
			NumExtensions: 0,
			NumServices:   0,
		},
		GoTypes:           file_packet_proto_goTypes,
		DependencyIndexes: file_packet_proto_depIdxs,
		EnumInfos:         file_packet_proto_enumTypes,
		MessageInfos:      file_packet_proto_msgTypes,
	}.Build()
	File_packet_proto = out.File
	file_packet_proto_rawDesc = nil
	file_packet_proto_goTypes = nil
	file_packet_proto_depIdxs = nil
}


<|start_filename|>pkg/logutil/logutil.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package logutil

import (
	"os"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// InitLogger initialize the global logger
func InitLogger() {
	// Preflight the logger
	config := zap.NewDevelopmentEncoderConfig()
	encoder := zapcore.NewConsoleEncoder(config)
	logger := zap.New(zapcore.NewCore(encoder, os.Stdout, Level()))
	zap.ReplaceGlobals(logger)
}


<|start_filename|>node/entry/systray/systray_darwin.go<|end_filename|>
package systray

/*
#cgo darwin CFLAGS: -DDARWIN -x objective-c -fobjc-arc
#cgo darwin LDFLAGS: -framework Cocoa -framework WebKit

#include "systray.h"
*/
import "C"

import (
	"unsafe"
)

// SetTemplateIcon sets the systray icon as a template icon (on Mac), falling back
// to a regular icon on other platforms.
// templateIconBytes should be the content of .ico for windows and
// .ico/.jpg/.png for other platforms.
func SetTemplateIcon(templateIconBytes []byte) {
	cstr := (*C.char)(unsafe.Pointer(&templateIconBytes[0]))
	C.set_icon(cstr, (C.int)(len(templateIconBytes)), true)
}


<|start_filename|>node/driver/events_monitor.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package driver

import (
	"context"
	"fmt"

	"github.com/pairmesh/pairmesh/internal/relay"
	"github.com/pairmesh/pairmesh/node/monitor"

	"go.uber.org/zap"
)

// eventsMonitor updates the local endpoints to the primary relay server periodically.
func (d *NodeDriver) eventsMonitor(ctx context.Context) {
	defer d.wg.Done()

	for {
		select {
		case e := <-d.rm.Events():
			// Only care about the relay server status of connected/closed.
			switch e.Type {
			case relay.EventTypeClientConnected:
				event := e.Data.(relay.EventClientConnected)
				priID := d.rm.PrimaryServerID()
				if priID != event.RelayServer.ID {
					continue
				}
				d.primaryServerConnected = true

			case relay.EventTypeClientClosed:
				event := e.Data.(relay.EventClientClosed)
				priID := d.rm.PrimaryServerID()
				if priID != event.RelayServer.ID {
					continue
				}
				d.primaryServerConnected = false
			}

		case e := <-d.mon.Events():
			switch e.Type {
			case monitor.EventTypeExternalAddressChanged:
				event := e.Data.(monitor.EventExternalAddressChanged)
				zap.L().Info("ExternalAddressChanged", zap.String("address", event.ExternalAddress))
				d.externalAddr.Store(event.ExternalAddress)

				// Latest endpoints.
				endpoints := []string{event.ExternalAddress}
				for _, l := range d.localAddresses() {
					endpoints = append(endpoints, fmt.Sprintf("%s:%d", l, d.config.Port))
				}

				d.mm.SyncEndpoints(endpoints)
			}

		case <-ctx.Done():
			zap.L().Info("Local events monitor stopped")
			return
		}
	}
}


<|start_filename|>portal/db/models/ip_allocator.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package models

import (
	"fmt"
	"math/rand"

	"gorm.io/gorm"
	"inet.af/netaddr"
)

const maxRetry = 200

// NextIP retrieve the next available IP address
// TODO: maybe use algorithm like
func NextIP(tx *gorm.DB) (string, error) {
	n := func(n int) byte { return byte(rand.Intn(n)) }
	var nextIP string
	var device Device
	for i := 0; i < maxRetry; i++ {
		ip := netaddr.IPFrom4([4]byte{10, n(256), n(256), 2 + n(253)})
		nextIP = ip.String()
		err := NewDeviceQuerySet(tx).AddressEq(nextIP).One(&device)
		if err == gorm.ErrRecordNotFound {
			return nextIP, nil
		}
	}
	return "", fmt.Errorf("found IP reach max retry count")
}


<|start_filename|>security/credential_test.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package security_test

import (
	"crypto/rand"
	"crypto/rsa"
	"net"
	"testing"
	"time"

	"github.com/pairmesh/pairmesh/protocol"
	"github.com/pairmesh/pairmesh/security"
	"github.com/stretchr/testify/assert"
)

func TestCredential(t *testing.T) {
	a := assert.New(t)

	privateKey, err := rsa.GenerateKey(rand.Reader, 512)
	a.Nil(err)

	var (
		userID = protocol.UserID(88888)
		peerID = protocol.PeerID(12345678)
		ip     = net.IP{0x01, 0x02, 0x03, 0x04}
	)

	credential, err := security.Credential(privateKey, userID, peerID, ip, time.Second*10)
	a.Nil(err)
	a.NotNil(credential)

	userID2, peerID2, ip2, valid := security.VerifyCredential(&privateKey.PublicKey, credential)
	a.True(valid)
	a.Equal(peerID2, peerID)
	a.Equal(userID2, userID)
	a.Equal(ip2, ip)
}

func TestCredentialIPv6(t *testing.T) {
	a := assert.New(t)

	privateKey, err := rsa.GenerateKey(rand.Reader, 512)
	a.Nil(err)

	var (
		userID = protocol.UserID(88888)
		peerID = protocol.PeerID(12345678)
		ip     = net.IPv6zero
	)

	credential, err := security.Credential(privateKey, userID, peerID, ip, time.Second*10)
	a.Nil(err)
	a.NotNil(credential)

	userID2, peerID2, ip2, valid := security.VerifyCredential(&privateKey.PublicKey, credential)
	a.True(valid)
	a.Equal(peerID2, peerID)
	a.Equal(userID2, userID)
	a.Equal(ip2, ip)
}

func TestCredentialExpired(t *testing.T) {
	a := assert.New(t)

	privateKey, err := rsa.GenerateKey(rand.Reader, 512)
	a.Nil(err)

	var (
		userID = protocol.UserID(88888)
		peerID = protocol.PeerID(12345678)
		ip     = net.IP{0x01, 0x02, 0x03, 0x04}
	)

	credential, err := security.Credential(privateKey, userID, peerID, ip, -time.Second*10)
	a.Nil(err)
	a.NotNil(credential)

	userID2, peerID2, ip2, valid := security.VerifyCredential(&privateKey.PublicKey, credential)
	a.False(valid)
	a.Zero(peerID2)
	a.Zero(userID2)
	a.Nil(ip2)
}

func TestCredentialCompromised(t *testing.T) {
	a := assert.New(t)

	privateKey, err := rsa.GenerateKey(rand.Reader, 512)
	a.Nil(err)

	var (
		userID = protocol.UserID(88888)
		peerID = protocol.PeerID(12345678)
		ip     = net.IP{0x01, 0x02, 0x03, 0x04}
	)

	credential, err := security.Credential(privateKey, userID, peerID, ip, time.Second*10)
	a.Nil(err)
	a.NotNil(credential)

	// Compromise and change one bit in credential
	credential[0] = credential[0] + 1

	userID2, peerID2, ip2, valid := security.VerifyCredential(&privateKey.PublicKey, credential)
	a.False(valid)
	a.Zero(peerID2)
	a.Zero(userID2)
	a.Nil(ip2)
}


<|start_filename|>internal/relay/server_test.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package relay

import (
	"crypto/rand"
	"crypto/rsa"
	"fmt"
	"testing"
	"time"

	"github.com/flynn/noise"
	gomock "github.com/golang/mock/gomock"
	"github.com/pairmesh/pairmesh/protocol"
	"github.com/stretchr/testify/assert"
	"go.uber.org/atomic"
)

// Handy util function to create a default server for testing.
func createServer(t *testing.T) *Server {
	port := 10042
	addr := fmt.Sprintf("127.0.0.1:%d", port)
	duration := 5 * time.Second
	serverDHKey, err := noise.DH25519.GenerateKeypair(rand.Reader)
	assert.Nil(t, err)
	priv, err := rsa.GenerateKey(rand.Reader, 512)
	assert.Nil(t, err)
	s := NewServer(addr, duration, serverDHKey, &priv.PublicKey)
	return s
}

func TestGetHeartbeatInterval(t *testing.T) {
	s := createServer(t)

	duration := s.HeartbeatInterval()

	assert.Equal(t, duration, 5*time.Second)
}

func TestGetHandler(t *testing.T) {
	s := createServer(t)

	handler := s.Handler()

	assert.True(t, handler == s.handler)
}

func TestGetDHKey(t *testing.T) {
	s := createServer(t)

	dhKey := s.DHKey()

	assert.Equal(t, dhKey, s.dhKey)
}

func TestGetRSAPublicKey(t *testing.T) {
	s := createServer(t)

	publicKey := s.RSAPublicKey()

	assert.True(t, publicKey == s.publicKey)
}

func TestSetRSAPublicKey(t *testing.T) {
	s := createServer(t)

	oldPublicKey := s.RSAPublicKey()
	newPriv, err := rsa.GenerateKey(rand.Reader, 512)
	assert.Nil(t, err)

	newPublicKey := &newPriv.PublicKey
	s.SetRSAPublicKey(newPublicKey)

	assert.False(t, newPublicKey == oldPublicKey)
	assert.True(t, newPublicKey == s.publicKey)

}

func TestGetSessionFound(t *testing.T) {
	s := createServer(t)

	ses := &Session{}
	peerID := protocol.PeerID(42)
	s.sessions.Store(peerID, ses)

	storedSes := s.Session(peerID)

	assert.True(t, ses == storedSes)
}

func TestGetSessionNotFound(t *testing.T) {
	s := createServer(t)

	peerID := protocol.PeerID(42)

	storedSes := s.Session(peerID)

	assert.Nil(t, storedSes)
}

func TestForeachSession(t *testing.T) {
	s := createServer(t)

	peers := 100

	for id := 0; id < peers; id++ {
		ses := &Session{}
		peerID := protocol.PeerID(id)
		ses.peerID = peerID
		s.sessions.Store(peerID, ses)
	}

	peerIDMap := map[protocol.PeerID]bool{}

	f := func(ses *Session) {
		peerID := ses.PeerID()
		peerIDMap[peerID] = true
	}

	s.ForeachSession(f)

	for id := 0; id < peers; id++ {
		peerID := protocol.PeerID(id)
		assert.True(t, peerIDMap[peerID])
	}
}

// Basic happy case:
// Server is ramped up new, and then handshake with a new session.
func TestOnSessionHandshake(t *testing.T) {
	s := createServer(t)

	ses := &Session{}
	peerID := protocol.PeerID(42)
	ses.peerID = peerID

	s.OnSessionHandshake(ses)

	storedSes, exists := s.sessions.Load(peerID)
	assert.True(t, exists)
	// To assert two pointers equal to each other, the assert.True() should be the method,
	// rather than the assert.Equal().
	// https://github.com/stretchr/testify/issues/597
	assert.True(t, ses == storedSes)
}

// The scenario that the server is closed,
// therefore the session should not be handshaked.
func TestOnSessionHandshakeServerClosed(t *testing.T) {
	s := createServer(t)
	s.closed.Store(true)

	ses := &Session{}

	peerID := protocol.PeerID(42)
	ses.peerID = peerID

	s.OnSessionHandshake(ses)

	_, exists := s.sessions.Load(peerID)
	assert.False(t, exists)

}

// The scenario that the server already has a session stored,
// then trying to handshake with another session with same peerID.
// Test the old session is popped and closed while the new sessoin
// is inserted to the session map.
func TestOnSessionHandshakeSessionExisted(t *testing.T) {
	s := createServer(t)

	ctrl := gomock.NewController(t)
	transporter := NewMockSessionTransporter(ctrl)
	peerID := protocol.PeerID(42)
	oldSes := &Session{
		SessionTransporter: transporter,
		lifetimeHook:       s,
		closed:             atomic.NewBool(false),
		peerID:             peerID,
	}
	transporter.EXPECT().Close().Return(nil).Times(1)
	newSes := &Session{
		peerID: peerID,
	}

	// Store the oldSes into the server s.
	s.sessions.Store(peerID, oldSes)

	s.OnSessionHandshake(newSes)

	storedSes, exists := s.sessions.Load(peerID)
	assert.True(t, exists)
	assert.True(t, storedSes == newSes)
}

// The scenario that the peerID of the session is 0.
// In this case the session should not be handshaked.
func TestOnSessionHandshakeSessionPeerIDZero(t *testing.T) {
	s := createServer(t)

	ses := &Session{}
	peerID := protocol.PeerID(0)
	ses.peerID = peerID

	s.OnSessionHandshake(ses)

	_, exists := s.sessions.Load(peerID)
	assert.False(t, exists)
}

// Basic normal case:
// Session is closed so remove it from s.sessions.
func TestOnSessionClosed(t *testing.T) {
	s := createServer(t)

	storedSes := &Session{}
	deleteSes := &Session{}

	peerID := protocol.PeerID(42)

	s.sessions.Store(peerID, storedSes)

	deleteSes.peerID = peerID

	s.OnSessionClosed(deleteSes)

	_, exist := s.sessions.Load(peerID)
	assert.False(t, exist)
}

// Scenario that the server is already closed.
// In this case the onSessionClosed() function should return fast.
func TestOnSessionClosedServerClosed(t *testing.T) {
	s := createServer(t)
	s.closed.Store(true)

	deleteSes := &Session{}

	peerID := protocol.PeerID(42)

	deleteSes.peerID = peerID

	s.OnSessionClosed(deleteSes)

	_, exist := s.sessions.Load(peerID)
	assert.False(t, exist)
}

// Scenario that the session's peerID is 0.
// In this case the onSessionClosed() function should return fast.
func TestOnSessionClosedSessionPeerIDZero(t *testing.T) {
	s := createServer(t)

	deleteSes := &Session{}

	peerID := protocol.PeerID(0)

	deleteSes.peerID = peerID

	s.OnSessionClosed(deleteSes)

	_, exist := s.sessions.Load(peerID)
	assert.False(t, exist)
}

func TestClose(t *testing.T) {
	s := createServer(t)

	ctrl := gomock.NewController(t)

	peers := 100
	for id := 0; id < peers; id++ {
		peerID := protocol.PeerID(id)
		transporter := NewMockSessionTransporter(ctrl)
		ses := &Session{
			SessionTransporter: transporter,
			lifetimeHook:       s,
			closed:             atomic.NewBool(false),
			peerID:             peerID,
		}
		transporter.EXPECT().Close().Return(nil).Times(1)
		s.sessions.Store(peerID, ses)
	}

	err := s.Close()

	assert.Nil(t, err)
}


<|start_filename|>relay/server/serve.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"context"
	"fmt"
	"sync"

	"github.com/pairmesh/pairmesh/constant"
	"github.com/pairmesh/pairmesh/internal/relay"
	"github.com/pairmesh/pairmesh/relay/api"
	"github.com/pairmesh/pairmesh/relay/config"
	"go.uber.org/zap"
)

// Serve run the Relay & STUN services
func Serve(ctx context.Context, wg *sync.WaitGroup, cfg *config.Config) error {
	zap.L().Info("Relay server is starting up...")

	apiClient := api.NewClient(cfg.Portal.URL, cfg.Portal.Key)

	// Start first keepalive ticker to retrieve the latest information of portal service.
	publicKey, _, err := keepaliveWithPortal(apiClient, cfg, nil)
	if err != nil {
		return err
	}

	// Preflight the relay server
	addr := fmt.Sprintf(":%d", cfg.Port)
	server := relay.NewServer(addr, constant.HeartbeatInterval, cfg.DHKey.ToNoiseDHKey(), publicKey)

	// Register the packet customized callback.
	registerCallback(server)

	// Start the keepalive goroutine to keep alive with the portal service.
	wg.Add(1)
	go keepalive(ctx, wg, server, apiClient, cfg)

	// Start serving STUN service to assist the PairMesh nodes to detect their external addresses.
	wg.Add(1)
	go serveSTUN(ctx, cfg, wg)

	zap.L().Info("Relay server ready to serve", zap.String("addr", addr))

	return server.Serve(ctx)
}


<|start_filename|>relay/server/callbacks.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package server

import (
	"github.com/pairmesh/pairmesh/internal/relay"
	"github.com/pairmesh/pairmesh/message"
	"github.com/pairmesh/pairmesh/pkg/logutil"
	"github.com/pairmesh/pairmesh/protocol"
	"go.uber.org/zap"
	"google.golang.org/protobuf/proto"
)

type (
	callbacks struct {
		server *relay.Server
	}
)

func registerCallback(server *relay.Server) {
	callback := &callbacks{server: server}
	server.Handler().On(message.PacketType_Forward, callback.onForward)
	server.Handler().On(message.PacketType_SyncPeer, callback.onSyncPeer)
	server.Handler().On(message.PacketType_ProbeRequest, callback.onProbe)
}

func (h *callbacks) onForward(self *relay.Session, _ message.PacketType, msg proto.Message) error {
	forward := msg.(*message.PacketForward)
	if logutil.IsEnableRelay() {
		zap.L().Debug("On forward", zap.Stringer("msg", forward), zap.Any("peer_id", self.PeerID()))
	}

	peerSession := h.server.Session(protocol.PeerID(forward.DstPeerID))
	if peerSession == nil {
		zap.L().Error("Peer session not found", zap.Any("peer_id", forward.DstPeerID))
		return nil
	}

	return peerSession.Send(message.PacketType_Forward, forward)
}

func (h *callbacks) onProbe(self *relay.Session, _ message.PacketType, msg proto.Message) error {
	probe := msg.(*message.PacketProbeRequest)
	if logutil.IsEnableRelay() {
		zap.L().Debug("On probe", zap.Stringer("msg", probe), zap.Any("peer_id", self.PeerID()))
	}

	res := &message.PacketProbeResponse{}
	for _, peerID := range probe.Peers {
		peerSession := h.server.Session(protocol.PeerID(peerID))
		if peerSession == nil {
			res.OfflinePeers = append(res.OfflinePeers, peerID)
		} else {
			res.OnlinePeers = append(res.OnlinePeers, peerID)
		}
	}

	return self.Send(message.PacketType_ProbeResponse, res)
}

func (h *callbacks) onSyncPeer(self *relay.Session, _ message.PacketType, msg proto.Message) error {
	syncPeer := msg.(*message.PacketSyncPeer)
	if logutil.IsEnableRelay() {
		zap.L().Debug("On sync peer", zap.Stringer("msg", syncPeer), zap.Any("peer_id", self.PeerID()))
	}

	peerSession := h.server.Session(protocol.PeerID(syncPeer.DstPeerID))
	if peerSession == nil {
		zap.L().Error("Peer session not found", zap.Any("peer_id", syncPeer.DstPeerID))
		return nil
	}

	return peerSession.Send(message.PacketType_SyncPeer, syncPeer)
}


<|start_filename|>node/device/tun/tun.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tun

import "io"

// DefaultMTU represents the default Maximum Transmission Unit
const DefaultMTU = 1420

// Device represents a layer-three virtual network device
type Device interface {
	Name() string
	io.ReadWriteCloser
}

type generalDevice struct {
	name string
	io.ReadWriteCloser
}

// Name implements the Device interface
func (d *generalDevice) Name() string {
	return d.name
}


<|start_filename|>portal/config/config_test.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package config_test

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/pairmesh/pairmesh/portal/config"

	"github.com/google/uuid"
	"github.com/stretchr/testify/assert"
)

func TestNew(t *testing.T) {
	cfg := config.New()
	a := assert.New(t)
	a.NotNil(cfg)
	a.Equal(cfg.Port, 2823)
	a.Equal(cfg.TLSCert, "")
	a.Equal(cfg.MySQL.Port, 3306)
	a.Equal(cfg.MySQL.Password, "")
	a.Equal(cfg.MySQL.DB, "pairportal")
}

func TestFromBytes(t *testing.T) {
	data := []byte(`
host: 0.0.0.0
port: 2824
tlsKey: "/path/to/tls/key"
tlsCert: "/path/to/tls/cert"

mysql:
  host: 127.0.0.1
  port: 4000
  user: root
  password: "password"
  db: pairportal
`)
	cfg, err := config.FromBytes(data)

	a := assert.New(t)
	a.Nil(err)
	a.Equal(cfg.TLSCert, "/path/to/tls/cert")
	a.Equal(cfg.MySQL.Port, 4000)
	a.Equal(cfg.MySQL.Password, "password")
	a.Equal(cfg.MySQL.DB, "pairportal")
}

func TestFromPath(t *testing.T) {
	path := filepath.Join(t.TempDir(), uuid.New().String())
	err := ioutil.WriteFile(path, []byte(`
host: 0.0.0.0
port: 2823
tlsKey: ''
tlsCert: /path/to/tls/cert
privateKey: /path/to/private-key
relay:
  authKey: test
sso:
  redirect: 'http://192.168.0.101:8080'
mysql:
  host: 127.0.0.1
  port: 3306
  user: root
  password: '<PASSWORD>'
  db: pairportal
`), os.ModePerm)

	a := assert.New(t)
	a.Nil(err)

	cfg, err := config.FromPath(path)
	a.Nil(err)
	a.Equal(cfg.TLSCert, "/path/to/tls/cert")
	a.Equal(cfg.PrivateKey, "/path/to/private-key")
	a.Equal(cfg.Relay.AuthKey, "test")
	a.Equal(cfg.MySQL.Port, 3306)
	a.Equal(cfg.MySQL.Password, "<PASSWORD>")
	a.Equal(cfg.MySQL.DB, "pairportal")
}


<|start_filename|>portal/webui/vue.config.js<|end_filename|>
// https://cli.vuejs.org/zh/config/#pages
module.exports = {
    assetsDir: 'assets',
    // CDN address
    publicPath: '/',
    pages: {
        main: {
            entry: 'src/main.js',
            filename: 'index.html'
        },
        console: {
            entry: 'src/console/main.js',
            filename: 'console/index.html'
        },
        login: {
            entry: 'src/login/main.js',
            filename: 'login/index.html'
        }
    },
    devServer: {
        proxy: {
            '/api/': {
                target: 'http://localhost:2823',
                changeOrigin: true
            },
        }
    }
}

<|start_filename|>node/resources/resource_windows.go<|end_filename|>
// Copyright 2021 PairMesh.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

package resources

import (
	"bytes"
	_ "embed"
	"image"
	_ "image/png"

	"github.com/lxn/walk"
)

//go:embed logo.png
var logo []byte

var (
	Logo walk.Image
)

func init() {
	Logo = mustLoadIcon(logo)
}

func mustLoadIcon(b []byte) walk.Image {
	img, _, err := image.Decode(bytes.NewReader(b))
	if err != nil {
		panic(err)
	}
	ret, err := walk.NewIconFromImageForDPI(img, 96) // NEW
	if err != nil {
		panic(err)
	}
	return ret
}


<|start_filename|>node/device/tun/tun_linux.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package tun

import (
	"fmt"
	"os"
	"syscall"
	"unsafe"

	"github.com/pkg/errors"
	"golang.org/x/sys/unix"
)

const (
	cloneDevicePath = "/dev/net/tun"
	ifReqSize       = unix.IFNAMSIZ + 64
)

// NewTUN creates a new TUN device and set the address to the specified address
func NewTUN(name string) (Device, error) {
	nfd, err := syscall.Open(cloneDevicePath, os.O_RDWR|syscall.O_NONBLOCK, 0)
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {
			return nil, fmt.Errorf("CreateTUN(%q) failed; %s does not exist", name, cloneDevicePath)
		}
		return nil, err

	}

	errno := setDeviceName(nfd, name)
	if errno != nil {
		return nil, errno
	}

	// Set MTU
	setmtu := func() error {
		// open datagram socket
		fd, err := unix.Socket(
			unix.AF_INET,
			unix.SOCK_DGRAM,
			0,
		)

		if err != nil {
			return err
		}

		defer unix.Close(fd)

		var setmtu [ifReqSize]byte
		copy(setmtu[:], name)
		*(*uint32)(unsafe.Pointer(&setmtu[unix.IFNAMSIZ])) = uint32(DefaultMTU)

		_, _, errno := unix.Syscall(
			unix.SYS_IOCTL,
			uintptr(fd),
			uintptr(unix.SIOCSIFMTU),
			uintptr(unsafe.Pointer(&setmtu[0])),
		)

		if errno != 0 {
			return errors.New("failed to set MTU of TUN device")
		}
		return nil
	}

	err = setmtu()
	if err != nil {
		return nil, err
	}

	err = unix.SetNonblock(nfd, true)
	if err != nil {
		return nil, err
	}

	fname := fmt.Sprintf("pairmeshDeviceFile/%d", nfd)
	dev := &generalDevice{
		name:            name,
		ReadWriteCloser: os.NewFile(uintptr(nfd), fname),
	}

	return dev, nil
}

// setDeviceName set device name with the file descriptor
func setDeviceName(nfd int, name string) error {

	var ifr [ifReqSize]byte
	var flags uint16 = unix.IFF_TUN | unix.IFF_NO_PI //(disabled for TUN status hack)
	nameBytes := []byte(name)
	if len(nameBytes) >= unix.IFNAMSIZ {
		return fmt.Errorf("interface name too long: %w", unix.ENAMETOOLONG)
	}
	copy(ifr[:], nameBytes)
	*(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags

	_, _, errno := unix.Syscall(
		unix.SYS_IOCTL,
		uintptr(nfd),
		uintptr(unix.TUNSETIFF),
		uintptr(unsafe.Pointer(&ifr[0])),
	)
	if errno != 0 {
		return errno
	}
	return nil
}


<|start_filename|>node/device/device_windows.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package device

import (
	"fmt"
	"github.com/pairmesh/pairmesh/node/device/firewall"
	"github.com/pairmesh/pairmesh/node/device/runner"

	"github.com/pairmesh/pairmesh/node/device/tun"
)

var _ Device = &device{}

type device struct {
	tun.Device
}

// NewDevice constructs a new virtual network interface device.
func NewDevice() (Device, error) {
	dev, err := tun.NewTUN()
	if err != nil {
		return nil, err
	}
	return &device{Device: dev}, nil
}

// Router implements the Device interface
func (d device) Router() Router {
	return newRouter(d)
}

// Up implements the Device interface.
func (d device) Up(address string) error {
	// Set the IP address for the virtual interface
	setAddress := []string{
		"netsh",
		"interface",
		"ip",
		"set",
		"address",
		fmt.Sprintf(`name="%s"`, d.Name()),
		fmt.Sprintf("addr=%s", address),
		"gateway=none",
	}
	err := runner.Run(setAddress)
	if err != nil {
		return err
	}

	upDevice := []string{
		"netsh",
		"interface",
		"set",
		"interface",
		fmt.Sprintf("\"%s\"", d.Name()),
		"enable",
	}

	// Async setup firewall rules when process startup.
	go firewall.Setup(address)

	return runner.Run(upDevice)
}

// Down implements the Device interface.
func (d device) Down() error {
	downDevice := []string{
		"netsh",
		"interface",
		"set",
		"interface",
		fmt.Sprintf("\"%s\"", d.Name()),
		"disable",
	}

	return runner.Run(downDevice)
}


<|start_filename|>relay/config/config.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package config

import (
	"bytes"
	"crypto/rand"
	"encoding/base64"
	"io"
	"io/ioutil"
	"os"
	"time"

	"github.com/flynn/noise"
	"github.com/pairmesh/pairmesh/security"
	"go.uber.org/zap"
	"gopkg.in/yaml.v3"
)

// Config represents the configuration of the relay server
type Config struct {
	// Name is a unique node name (across all regions).
	// It is not a host name.
	// It's typically of the form "1b", "2a", "3b", etc. (region
	// ID + suffix within that region)
	Name string `yaml:"name"`

	// Region is the Region of the RelayRegion that this node
	// is running in.
	Region string `yaml:"region"`

	// Host describes the host information about the relay server.
	Host string `yaml:"host,omitempty"`

	Port int `yaml:"port,omitempty"`

	// Port optionally specifies a STUN port to use.
	// Zero means 3478.
	// To disable STUN on this node, use -1.
	// https://datatracker.ietf.org/doc/html/rfc5389#section-18.4
	STUNPort int `yaml:"stunPort,omitempty"`

	DHKey  *security.DHKey `yaml:"dhKey"`
	Portal *Portal         `yaml:"portal"`
}

// Portal represents the gateway instance configuration
type Portal struct {
	Key string `yaml:"key"`
	URL string `yaml:"url"`
	// Keepalive interval between portal/relay services.
	KeepaliveInterval time.Duration `yaml:"keepaliveInterval,omitempty"`
	// Sync peer online status after a sync interval.
	SyncInterval time.Duration `yaml:"syncInterval,omitempty"`
}

// New returns a config instance with default value
func New() *Config {
	return &Config{
		Name:     "1a",
		Region:   "testing",
		Port:     2328,
		STUNPort: 3478,

		Portal: &Portal{
			Key:               "testing-relay-server",
			URL:               "http://127.0.0.1:2823",
			KeepaliveInterval: 5 * time.Minute,
			SyncInterval:      5 * time.Minute,
		},
	}
}

// FromReader returns the configuration instance from reader
func FromReader(reader io.Reader) (*Config, error) {
	c := New()
	err := yaml.NewDecoder(reader).Decode(c)
	if err != nil {
		return nil, err
	}

	return c, nil
}

// FromBytes returns the configuration instance from bytes
func FromBytes(data []byte) (*Config, error) {
	reader := bytes.NewBuffer(data)
	return FromReader(reader)
}

// FromPath returns the configuration instance from file path
func FromPath(path string) (*Config, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	cfg, err := FromBytes(data)
	if err != nil {
		return nil, err
	}

	if cfg.DHKey == nil || cfg.DHKey.Public.Len() != noise.DH25519.DHLen() {
		// Generate the static key for the current node.
		staticKey, err := noise.DH25519.GenerateKeypair(rand.Reader)
		if err != nil {
			return nil, err
		}
		cfg.DHKey = security.FromNoiseDHKey(staticKey)
		zap.L().Info("Generate key", zap.String("publicKey", base64.RawStdEncoding.EncodeToString(staticKey.Public)))

		// Save to the configuration.
		file, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, os.ModePerm)
		if err != nil {
			return nil, err
		}
		defer file.Close()

		err = yaml.NewEncoder(file).Encode(cfg)
		if err != nil {
			return nil, err
		}
	}

	return cfg, nil
}


<|start_filename|>node/device/device.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package device

import "io"

// Device represents the abstraction of virtual network interface device.
// The Device interface has different implementation for cross platform.
// 1. Windows: use wintun-go project to manage layer-three virtual interface.
// 2. Linux: use /dev/tun file to create layer-three tun file descriptor.
// 3. macOS: use /dev/utun file to create layer-three tun file descriptor.
// 4. Android: use VPN service interface to create low-level resource.
// 5. iOS: use Network extension to create VPN service.
type Device interface {
	io.ReadWriteCloser

	// Name returns the name of the Peerly virtual network device.
	Name() string

	// Router returns the router of the current device.
	Router() Router

	// Up runs the device with the address of the virtual tunnel device.
	Up(ipv4 string) error

	// Down closed the virtual device
	Down() error
}


<|start_filename|>node/device/router_freebsd.go<|end_filename|>
package device

import "inet.af/netaddr"

func (r *router) add(devName string, localAddress netaddr.IP, target netaddr.IPPrefix) error {
	return bsdAdd(devName, localAddress, target)
}

func (r *router) del(devName string, localAddress netaddr.IP, target netaddr.IPPrefix) error {
	return bsdDel(devName, localAddress, target)
}


<|start_filename|>node/mesh/manager_test.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mesh

import (
	"testing"

	"github.com/pairmesh/pairmesh/message"
	"github.com/pairmesh/pairmesh/protocol"
	"github.com/stretchr/testify/assert"
)

func setupManager() *Manager {
	manager := Manager{}
	networks := []protocol.Network{}
	manager.networks.Store(networks)
	return &manager
}

func findPeerInNetwork(manager *Manager, networkID uint64, peerID uint64) bool {
	var networks []protocol.Network
	if v := manager.networks.Load(); v != nil {
		networks = v.([]protocol.Network)
	}
	for _, network := range networks {
		if network.ID == protocol.NetworkID(networkID) {
			for _, currID := range network.Peers {
				if currID == protocol.PeerID(peerID) {
					return true
				}
			}
		}
	}
	return false
}

func TestUpdateNetworkTopologyWithPeer(t *testing.T) {
	a := assert.New(t)
	manager := setupManager()
	networks := []protocol.Network{
		{
			ID:    protocol.NetworkID(1),
			Peers: []protocol.PeerID{1, 2, 3, 42, 100},
		},
		{
			ID:    protocol.NetworkID(2),
			Peers: []protocol.PeerID{1, 2},
		},
		{
			ID:    protocol.NetworkID(4),
			Peers: []protocol.PeerID{42},
		},
	}
	manager.networks.Store(networks)

	peerNetworks := []*message.PacketSyncPeer_Network{
		{ID: 2},
		{ID: 3},
		{ID: 4},
	}

	peerInfo := message.PacketSyncPeer_PeerInfo{
		PeerID:   42,
		Networks: peerNetworks,
	}

	manager.updateNetworkTopologyWithPeer(&peerInfo)
	// Peer 42 should be removed from network 1 and added to network 2, 3,
	// and skip 4 since it's already there:
	// NetworkID  |  PeerIDs
	//         1  |        1, 2, 3, 100
	//         2  |        1, 2, 42
	//         3  |       42
	//         4  |       42
	for _, networkID := range []uint64{1, 2, 3, 100} {
		a.True(findPeerInNetwork(manager, 1, networkID))
	}
	a.False(findPeerInNetwork(manager, 1, 42))
	for _, networkID := range []uint64{1, 2, 42} {
		a.True(findPeerInNetwork(manager, 2, networkID))
	}
	a.True(findPeerInNetwork(manager, 3, 42))
	a.True(findPeerInNetwork(manager, 4, 42))
}

func TestUpdateNetworkTopologyWithPeerEmptyManagerNetwork(t *testing.T) {
	a := assert.New(t)
	manager := setupManager()

	peerNetworks := []*message.PacketSyncPeer_Network{
		{ID: 1},
		{ID: 2},
		{ID: 3},
	}

	peerInfo := message.PacketSyncPeer_PeerInfo{
		PeerID:   42,
		Networks: peerNetworks,
	}

	manager.updateNetworkTopologyWithPeer(&peerInfo)
	// Peer 42 together with new network 1, 2, 3 should be added to manager.
	// NetworkID | PeerIDs
	//         1 |      42
	//         2 |      42
	//         3 |      42
	a.True(findPeerInNetwork(manager, 1, 42))
	a.True(findPeerInNetwork(manager, 2, 42))
	a.True(findPeerInNetwork(manager, 3, 42))
	a.False(findPeerInNetwork(manager, 1, 1))
}

func TestUpdateNetworkTopologyWithPeerEmptyPeerInfo(t *testing.T) {
	a := assert.New(t)
	manager := setupManager()

	networks := []protocol.Network{
		{
			ID:    protocol.NetworkID(1),
			Peers: []protocol.PeerID{1, 2, 3, 42, 100},
		},
		{
			ID:    protocol.NetworkID(2),
			Peers: []protocol.PeerID{42},
		},
		{
			ID:    protocol.NetworkID(3),
			Peers: []protocol.PeerID{41},
		},
	}
	manager.networks.Store(networks)

	peerNetworks := []*message.PacketSyncPeer_Network{}

	peerInfo := message.PacketSyncPeer_PeerInfo{
		PeerID:   42,
		Networks: peerNetworks,
	}

	manager.updateNetworkTopologyWithPeer(&peerInfo)
	// Peer 42 should be removed from network 1 and 2.
	// NetworkID | PeerIDs
	//         1 |       1, 2, 3, 100
	//         2 |       N/A
	//         3 |       41
	for _, networkID := range []uint64{1, 2, 3, 100} {
		a.True(findPeerInNetwork(manager, 1, networkID))
	}
	a.False(findPeerInNetwork(manager, 1, 42))
	a.False(findPeerInNetwork(manager, 2, 42))
	a.True(findPeerInNetwork(manager, 3, 41))
	a.False(findPeerInNetwork(manager, 3, 42))
}


<|start_filename|>relay/config/config_test.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package config

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"

	"github.com/google/uuid"
	"github.com/stretchr/testify/assert"
)

func TestFromPath(t *testing.T) {
	dir := t.TempDir()
	fileName := fmt.Sprintf("%s.toml", uuid.New().String())
	path := filepath.Join(dir, fileName)
	data := []byte(`
name: 1a
region: '1'
host: 127.0.0.1
port: 2328
stunPort: 3478
portal:
  key: my-testing-relay
  url: 'http://127.0.0.1:2823'
`)
	err := ioutil.WriteFile(path, data, os.ModePerm)
	assert.Nil(t, err)

	cfg, err := FromPath(path)
	assert.Nil(t, err)

	assert.NotNil(t, cfg.DHKey.Public)
	assert.NotNil(t, cfg.DHKey.Private)

	data, err = ioutil.ReadFile(path)
	assert.Nil(t, err)

	assert.Contains(t, string(data), "dhKey")

	// Double check
	cfg2, err := FromPath(path)
	assert.Nil(t, err)
	assert.Equal(t, cfg.DHKey.Public, cfg2.DHKey.Public)
	assert.Equal(t, cfg.DHKey.Private, cfg2.DHKey.Private)
}


<|start_filename|>pkg/cmdutil/cmd.go<|end_filename|>
// Copyright 2021 PairMesh, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmdutil

import (
	"fmt"
	"math/rand"
	"os"
	"strings"
	"time"

	"github.com/fatih/color"
	"github.com/spf13/cobra"
	"go.uber.org/zap"
)

// Example represents an example of command line
type Example struct {
	Example string
	Comment string
}

// Examples represents a group of examples
type Examples []Example

// String implements the fmt.Stringer interface
func (es Examples) String() string {
	if len(es) == 0 {
		return ""
	}

	var max int
	for _, e := range es {
		if len(e.Example) > max {
			max = len(e.Example)
		}
	}

	var all []string
	for _, e := range es {
		all = append(all, fmt.Sprintf("  %s%s# %s", Highlight(e.Example), strings.Repeat(" ", max-len(e.Example)+3), e.Comment))
	}

	return strings.Join(all, "\n")
}

// Run starts a command
func Run(cmd *cobra.Command) {
	rand.Seed(time.Now().UnixNano())

	if err := cmd.Execute(); err != nil {
		zap.L().Error("Run command failed", zap.Error(err))
		os.Exit(1)
	}
}

// Bold converts the string to bolder display in the terminal
func Bold(f string, args ...interface{}) string {
	return color.New(color.Bold).Sprintf(f, args...)
}

// Underline add the underline display in the terminal for the string
func Underline(f string, args ...interface{}) string {
	return color.New(color.Bold, color.Underline).Sprintf(f, args...)
}

// Highlight highlights the string in the terminal
func Highlight(f string, args ...interface{}) string {
	return color.New(color.Bold, color.FgHiCyan).Sprintf(f, args...)
}


<|start_filename|>tools/logserver/main.go<|end_filename|>
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"time"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		body, _ := ioutil.ReadAll(r.Body)
		fmt.Printf("%s [%s]%s %s\n", time.Now().String(), r.Method, r.URL, bytes.NewBuffer(body).String())
	})
	log.Fatal(http.ListenAndServe("0.0.0.0:5001", nil))
}
