staging updates just so jeremy can pick them up

This commit is contained in:
dovholuknf
2020-05-04 09:02:19 -04:00
parent 8a4b8ca9ce
commit ea2d2b97a8
14 changed files with 420 additions and 233 deletions
+1
View File
@@ -147,5 +147,6 @@
</StackPanel>
<local:MainMenu x:Name="MainMenu" Visibility="Collapsed"></local:MainMenu>
<local:IdentityDetails x:Name="IdentityMenu" Visibility="Collapsed"></local:IdentityDetails>
<Button Content="Button" HorizontalAlignment="Left" Margin="47,244,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</Window>
+12 -2
View File
@@ -71,6 +71,7 @@ namespace ZitiTunneler {
// add a new service client
serviceClient = new Client();
serviceClient.OnTunnelStatusUpdate += ServiceClient_OnTunnelStatusUpdated;
Application.Current.Properties.Add("ServiceClient", serviceClient);
Application.Current.Properties.Add("Identities", new List<ZitiIdentity>());
MainMenu.OnAttachmentChange += AttachmentChanged;
@@ -85,8 +86,12 @@ namespace ZitiTunneler {
IdentityMenu.OnForgot += IdentityForgotten;
}
private void ServiceClient_OnTunnelStatusUpdated(object sender, TunnelStatus e)
{
}
private void IdentityForgotten(ZitiIdentity forgotten) {
ZitiTunnelStatus status = serviceClient.GetStatus();
TunnelStatus status = serviceClient.GetStatus().Status;
identities.Clear();
foreach (var id in status.Identities) {
var zid = ZitiIdentity.FromClient(id);
@@ -112,7 +117,7 @@ namespace ZitiTunneler {
}
private void LoadStatusFromService() {
ZitiTunnelStatus status = serviceClient.GetStatus();
TunnelStatus status = serviceClient.GetStatus().Status;
if (status != null) {
if (status.Active) {
InitializeTimer((int)status.Duration);
@@ -257,5 +262,10 @@ namespace ZitiTunneler {
e.Cancel = true;
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//
}
}
}
+60 -15
View File
@@ -6,7 +6,8 @@ using System.Security.Principal;
using System.Security.AccessControl;
using Newtonsoft.Json;
using System.Threading;
using System.Threading.Tasks;
/// <summary>
/// The implementation will abstract away the setup of the communication to
@@ -19,13 +20,35 @@ using Newtonsoft.Json;
/// </summary>
namespace ZitiTunneler.ServiceClient
{
internal class Client
{
public event EventHandler<TunnelStatus> OnTunnelStatusUpdate;
public event EventHandler<Metrics> OnMetricsUpdate;
protected virtual void ZitiTunnelStatusUpdate(TunnelStatus e)
{
EventHandler<TunnelStatus> handler = OnTunnelStatusUpdate;
if (handler != null)
{
handler(this, e);
}
}
protected virtual void MetricsUpdate(Metrics e)
{
EventHandler<Metrics> handler = OnMetricsUpdate;
if (handler != null)
{
handler(this, e);
}
}
JsonSerializer serializer = new JsonSerializer();
private object namedPipeSyncLock = new object();
const string ipcPipe = @"NetFoundry\tunneler\ipc";
const string logPipe = @"NetFoundry\tunneler\logs";
const string eventPipe = @"NetFoundry\tunneler\events";
const string localPipeServer = ".";
const PipeDirection inOut = PipeDirection.InOut;
const int ServiceConnectTimeout = 500;
@@ -38,6 +61,23 @@ namespace ZitiTunneler.ServiceClient
{
//establish the named pipe to the service
setupPipe();
Task.Run(() => {
Console.WriteLine("THREAD BEGINS");
NamedPipeClientStream eventClient = new NamedPipeClientStream(localPipeServer, eventPipe, PipeDirection.In);
eventClient.Connect();
StreamReader eventReader = new StreamReader(eventClient);
while (true)
{
var r = read<StatusUpdateResponse>("event: ", eventReader);
if (eventReader.EndOfStream)
{
break;
}
Debug.WriteLine(r.Payload);
}
Console.WriteLine("THREAD DONE");
});
}
PipeSecurity CreateSystemIOPipeSecurity()
{
@@ -91,7 +131,7 @@ namespace ZitiTunneler.ServiceClient
try
{
send(new ServiceFunction() { Function = "Status" });
var rtn = read<ZitiTunnelStatus>();
var rtn = read<ZitiTunnelStatus>(" ipc: ", ipcReader);
return rtn;
}
catch (IOException ioe)
@@ -124,7 +164,7 @@ namespace ZitiTunneler.ServiceClient
send(AddIdentityFunction);
send(newId);
var resp = read<IdentityResponse>();
var resp = read<IdentityResponse>(" ipc: ", ipcReader);
Debug.WriteLine(resp.ToString());
return resp.Payload;
@@ -154,7 +194,7 @@ namespace ZitiTunneler.ServiceClient
Payload = new FingerprintPayload() { Fingerprint = fingerPrint }
};
send(removeFunction);
var r = read<SvcResponse>();
var r = read<SvcResponse>(" ipc: ", ipcReader);
}
catch (IOException ioe)
{
@@ -169,7 +209,7 @@ namespace ZitiTunneler.ServiceClient
try
{
send(new BooleanFunction("TunnelState", onOff));
read<SvcResponse>();
read<SvcResponse>(" ipc: ", ipcReader);
}
catch (IOException ioe)
{
@@ -206,7 +246,7 @@ namespace ZitiTunneler.ServiceClient
try
{
send(new IdentityToggleFunction(fingerprint, onOff));
IdentityResponse idr = read<IdentityResponse>();
IdentityResponse idr = read<IdentityResponse>(" ipc: ", ipcReader);
return idr.Payload;
}
catch (IOException ioe)
@@ -271,33 +311,33 @@ namespace ZitiTunneler.ServiceClient
}
}
private T read<T>() where T : SvcResponse
private T read<T>(string prefix, StreamReader reader) where T : SvcResponse
{
try
{
int emptyCount = 1;
Debug.WriteLine("=============== reading message =============== " + emptyCount);
string respAsString = ipcReader.ReadLine();
Debug.WriteLine(prefix + "=============== reading message =============== " + emptyCount);
string respAsString = reader.ReadLine();
Debug.WriteLine(respAsString);
Debug.WriteLine("=============== read message =============== " + emptyCount);
Debug.WriteLine(prefix + "=============== read message =============== " + emptyCount);
while (string.IsNullOrEmpty(respAsString?.Trim()))
{
//T resp = (T)serializer.Deserialize(reader, typeof(T));
if (ipcReader.EndOfStream)
if (reader.EndOfStream)
{
throw new Exception("the pipe has closed");
}
Debug.WriteLine("Received empty payload - continuing to read until a payload is received");
//now how'd that happen...
Debug.WriteLine("=============== reading message =============== " + emptyCount);
respAsString = ipcReader.ReadLine();
Debug.WriteLine(prefix + "=============== reading message =============== " + emptyCount);
respAsString = reader.ReadLine();
Debug.WriteLine(respAsString);
Debug.WriteLine("=============== read message =============== " + emptyCount);
Debug.WriteLine(prefix + "=============== read message =============== " + emptyCount);
emptyCount++;
if (emptyCount > 5)
{
Debug.WriteLine("are we there yet? " + ipcReader.EndOfStream);
Debug.WriteLine("are we there yet? " + reader.EndOfStream);
//that's just too many...
setupPipe();
return null;
@@ -320,6 +360,11 @@ namespace ZitiTunneler.ServiceClient
setupPipe();
throw ioe;
}
catch (Exception ee)
{
//almost certainly a problem with the pipe - recreate the pipe...
throw ee;
}
}
}
}
@@ -19,6 +19,18 @@ namespace ZitiTunneler.ServiceClient
}
}
class StatusUpdateResponse : SvcResponse
{
public StatusUpdate Payload { get; set; }
}
class StatusUpdate
{
public string Operation { get; set; }
public TunnelStatus Status { get; set; }
public Metrics Metrics { get; set; }
}
public class NewIdentity
{
public EnrollmentFlags Flags { get; set; }
@@ -96,6 +108,8 @@ namespace ZitiTunneler.ServiceClient
public class Metrics
{
public int TotalBytes { get; set; }
public double Upload { get; set; }
public double Download { get; set; }
}
public class Identity
@@ -132,6 +146,11 @@ namespace ZitiTunneler.ServiceClient
}
class ZitiTunnelStatus : SvcResponse
{
public TunnelStatus Status { get; set; }
}
class TunnelStatus
{
public bool Active { get; set; }
+1 -1
View File
@@ -15,8 +15,8 @@ require (
github.com/netfoundry/ziti-sdk-golang v0.11.16
github.com/sirupsen/logrus v1.5.0
github.com/tebeka/strftime v0.1.4 // indirect
github.com/tv42/topic v0.0.0-20130729201830-aa72cbe81b48
golang.org/x/sys v0.0.0-20200406113430-c6e801f48ba2
golang.zx2c4.com/wireguard v0.0.20200320
golang.zx2c4.com/wireguard/windows v0.1.0
gopkg.in/natefinch/lumberjack.v2 v2.0.0
)
+2 -2
View File
@@ -106,6 +106,8 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/tebeka/strftime v0.1.4 h1:e0FKSyxthD1Xk4cIixFPoyfD33u2SbjNngOaaC3ePoU=
github.com/tebeka/strftime v0.1.4/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
github.com/tv42/topic v0.0.0-20130729201830-aa72cbe81b48 h1:4HadKLQh7sw8SobBMRWhMOZXHm+Nyx+c9xfhJlWEI2Y=
github.com/tv42/topic v0.0.0-20130729201830-aa72cbe81b48/go.mod h1:b4JA15yUof03YRQ6IiKevPk2syaMBMJb92x9PeyU+Xc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -164,8 +166,6 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+21 -9
View File
@@ -1,11 +1,9 @@
package dto
import (
"log"
"github.com/netfoundry/ziti-sdk-golang/ziti/enroll"
idcfg "github.com/netfoundry/ziti-sdk-golang/ziti/config"
"github.com/netfoundry/ziti-sdk-golang/ziti/enroll"
"log"
"wintun-testing/ziti-tunnel/config"
)
@@ -44,11 +42,12 @@ type Response struct {
Error string
Payload interface{} `json:"Payload"`
}
type ZitiTunnelStatus struct {
Code int
Message string
Error string
Payload Identity
type TunIpInfo struct {
Ip string
Subnet string
MTU uint16
DNS string
}
func (id *Identity) Path() string {
@@ -57,3 +56,16 @@ func (id *Identity) Path() string {
}
return config.Path() + id.FingerPrint + ".json"
}
type TunnelStatus struct {
Active bool
Duration int64 `json:"-"`
Identities []*Identity
IpInfo *TunIpInfo `json:"IpInfo,omitempty"`
}
type ZitiTunnelStatus struct {
Status *TunnelStatus `json:",omitempty"`
Metrics *Metrics `json:",omitempty"`
}
+1
View File
@@ -51,6 +51,7 @@ func main() {
cmd := strings.ToLower(os.Args[1])
switch cmd {
case "debug":
service.Debug = true
service.RunService(true)
return
case "install":
+183 -141
View File
@@ -9,7 +9,6 @@ import (
"github.com/netfoundry/ziti-foundation/identity/identity"
"github.com/netfoundry/ziti-sdk-golang/ziti/enroll"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/eventlog"
"io"
"io/ioutil"
"net"
@@ -17,62 +16,40 @@ import (
"strings"
"time"
"wintun-testing/cziti"
"wintun-testing/ziti-tunnel/globals"
"wintun-testing/cziti/windns"
"wintun-testing/ziti-tunnel/config"
"wintun-testing/ziti-tunnel/dto"
"wintun-testing/ziti-tunnel/idutil"
"wintun-testing/ziti-tunnel/runtime"
)
type Pipes struct {
ipc net.Listener
logs net.Listener
events net.Listener
}
func(p *Pipes) Close() {
p.ipc.Close()
p.logs.Close()
p.events.Close()
}
func SubMain(ops <- chan string, changes chan<- svc.Status) error {
log.Debug("")
log.Debug("")
log.Debug("===============================================================================")
// open and assign the event log for this service
Elog, err := eventlog.Open(SvcName)
if err != nil {
return err
}
_ = Elog.Info(InformationEvent, SvcName + " starting. log file located at " + config.LogFile())
defer close(top.Broadcast)
log.Info("============================== service begins ==============================")
_ = globals.Elog.Info(InformationEvent, SvcName + " starting. log file located at " + config.LogFile())
// create a channel for notifying any connections that they are to be interrupted
interrupt = make(chan struct{})
// create the ACE string representing the following groups have access to the pipes created
grps := []string{InteractivelyLoggedInUser, System, BuiltinAdmins, LocalService}
auth := "D:" + strings.Join(grps, "")
// create the pipes
pc := winio.PipeConfig{
SecurityDescriptor: auth,
MessageMode: false,
InputBufferSize: 1024,
OutputBufferSize: 1024,
}
logs, err := winio.ListenPipe(logsPipeName, &pc)
pipes, err := openPipes()
if err != nil {
return err
}
// listen for log requests
go acceptLogs(logs)
log.Infof("log listener ready. pipe: %s", logsPipeName)
pc2 := winio.PipeConfig{
SecurityDescriptor: auth,
MessageMode: false,
InputBufferSize: 1024,
OutputBufferSize: 1024,
}
ipc, err := winio.ListenPipe(ipcPipeName, &pc2)
if err != nil {
return err
}
// listen for ipc messages
go acceptIPC(ipc)
log.Infof("ipc listener ready pipe: %s", ipcPipeName)
defer pipes.Close()
// wire in a log file for csdk troubleshooting
logFile, err := os.OpenFile(config.Path() + "cziti.log", os.O_WRONLY | os.O_TRUNC | os.O_APPEND | os.O_CREATE, 0644)
@@ -95,33 +72,80 @@ func SubMain(ops <- chan string, changes chan<- svc.Status) error {
// notify the service is running
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
_ = Elog.Info(InformationEvent, SvcName + " status set to running")
_ = globals.Elog.Info(InformationEvent, SvcName + " status set to running")
log.Info(SvcName + " status set to running. starting cancel loop")
loop:
for {
c := <-ops
log.Infof("request for control received, %v", c)
if c == "stop" {
break loop
} else {
log.Debug("unexpected operation: " + c)
}
}
waitForStopRequest(ops)
shutdownConnections()
pipes.shutdownConnections()
windns.ResetDNS()
state.Close()
_ = ipc.Close()
_ = logs.Close()
log.Info("shutdown complete. exiting process")
rts.Close()
log.Info("============================== service ends ==============================")
return nil
}
func waitForStopRequest(ops <- chan string) {
func shutdownConnections() {
loop:
for {
c := <-ops
log.Infof("request for control received, %v", c)
if c == "stop" {
break loop
} else {
log.Debug("unexpected operation: " + c)
}
}
}
func openPipes() (*Pipes, error) {
// create the ACE string representing the following groups have access to the pipes created
grps := []string{InteractivelyLoggedInUser, System, BuiltinAdmins, LocalService}
auth := "D:" + strings.Join(grps, "")
// create the pipes
pc := winio.PipeConfig{
SecurityDescriptor: auth,
MessageMode: false,
InputBufferSize: 1024,
OutputBufferSize: 1024,
}
logs, err := winio.ListenPipe(logsPipeName(), &pc)
if err != nil {
return nil, err
}
ipc, err := winio.ListenPipe(ipcPipeName(), &pc)
if err != nil {
return nil, err
}
events, err := winio.ListenPipe(eventsPipeName(), &pc)
if err != nil {
return nil, err
}
// listen for log requests
go accept(logs, serveLogs)
log.Infof("log listener ready. pipe: %s", logsPipeName())
// listen for ipc messages
go accept(ipc, serveIpc)
log.Infof("ipc listener ready pipe: %s", ipcPipeName())
// listen for events messages
go accept(events, serveEvents)
log.Infof("events listener ready pipe: %s", eventsPipeName())
return &Pipes{
ipc: ipc,
logs: logs,
events: events,
}, nil
}
func(p *Pipes) shutdownConnections() {
log.Info("waiting for all connections to close...")
for i := 0; i < connections; i++ {
@@ -132,7 +156,46 @@ func shutdownConnections() {
log.Info("all connections closed")
}
func acceptIPC(p net.Listener) {
func initialize() error {
rts.LoadConfig()
err := rts.CreateTun()
if err != nil {
return err
}
setTunInfo(rts.state)
s := rts.state
// decide if the tunnel should be active or not and if so - activate it
setTunnelState(s.Active)
// connect any identities that are enabled
for _, id := range s.Identities {
connectIdentity(id)
}
log.Debugf("initial state loaded from configuration file")
return nil
}
func setTunInfo(s *dto.TunnelStatus) {
//set the tun info into the state
s.IpInfo = &dto.TunIpInfo{
Ip: Ipv4ip,
DNS: Ipv4dns,
MTU: 1400,
Subnet: "255.255.255.0",
}
}
func closeConn(conn net.Conn) {
err := conn.Close()
if err != nil {
log.Warnf("abnormal error while closing connection. %v", err)
}
}
func accept(p net.Listener, serveFunction func(net.Conn)) {
for {
c, err := p.Accept()
if err != nil {
@@ -145,60 +208,7 @@ func acceptIPC(p net.Listener) {
connections ++
log.Debugf("accepting a new client")
go serveIpc(c)
}
}
func initialize() error {
log.Debugf("reading config file located at: %s", config.File())
file, err := os.OpenFile(config.File(), os.O_RDONLY, 0644)
if err != nil {
// file does not exist or process has no rights to read the file - return leaving configuration empty
// this is expected when first starting
return nil
}
r := bufio.NewReader(file)
dec := json.NewDecoder(r)
_ = dec.Decode(&state)
err = state.CreateTun()
if err != nil {
return err
}
setTunInfo()
// decide if the tunnel should be active or not and if so - activate it
setTunnelState(state.Active)
// connect any identities that are enabled
for _, id := range state.Identities {
connectIdentity(id)
}
err = file.Close()
if err != nil {
return fmt.Errorf("could not close configuration file. this is not normal! %v", err)
}
log.Debugf("initial state loaded from configuration file")
return nil
}
func setTunInfo() {
//set the tun info into the state
state.IpInfo = &runtime.TunIpInfo{
Ip: runtime.Ipv4ip,
DNS: runtime.Ipv4dns,
MTU: 1400,
Subnet: "255.255.255.0",
}
}
func closeConn(conn net.Conn) {
err := conn.Close()
if err != nil {
log.Warnf("abnormal error while closing connection. %v", err)
go serveFunction(c)
}
}
@@ -284,6 +294,11 @@ func serveIpc(conn net.Conn) {
onOff := cmd.Payload["OnOff"].(bool)
fingerprint := cmd.Payload["Fingerprint"].(string)
toggleIdentity(enc, fingerprint, onOff)
top.Broadcast <- dto.ZitiTunnelStatus{
Status: rts.ToStatus(),
Metrics: nil,
}
default:
log.Warnf("Unknown operation: %s. Returning error on pipe", cmd.Function)
respondWithError(enc, "Something unexpected has happened", UNKNOWN_ERROR, nil)
@@ -293,19 +308,6 @@ func serveIpc(conn net.Conn) {
log.Info("IPC Loop has exited")
}
func acceptLogs(p net.Listener) {
log.Debug("beginning logs receive loop")
for {
lcon, err := p.Accept()
if err != nil {
log.Errorf("unexpected error during accept. exiting accept loop! %v", err)
return
}
go serveLogs(lcon) //serveLogs will close the connection for us
}
}
func serveLogs(conn net.Conn) {
log.Debug("accepted a connection, writing logs to pipe")
w := bufio.NewWriter(conn)
@@ -344,14 +346,54 @@ func serveLogs(conn net.Conn) {
}
}
func serveEvents(conn net.Conn) {
log.Debug("accepted a connection, writing events to pipe")
consumer := make(chan interface{}, 1)
top.Register(consumer)
w := bufio.NewWriter(conn)
o := json.NewEncoder(w)
for {
msg := <-consumer
status, ok := msg.(dto.ZitiTunnelStatus)
if !ok {
log.Errorf("message received couldn't be converted to status? %v", status)
break
}
respond(o, dto.Response{Payload: status})
_, err := w.WriteString("\n")
if err != nil {
if err == io.EOF {
//fine client disconnected
log.Debug("exiting from serveEvents - client disconnected")
} else {
log.Errorf("exiting from serveEvents - unexpected error %v", err)
}
top.Unregister(consumer)
break
}
_ = w.Flush()
log.Infof("got %v", msg)
}
log.Info("exiting serve events")
}
func reportStatus(out *json.Encoder) {
log.Debugf("request for status")
respond(out, state.Clean())
respond(out, dto.ZitiTunnelStatus{
Status: rts.ToStatus(),
Metrics: nil,
})
log.Debugf("request for status responded to")
}
func tunnelState(onOff bool, out *json.Encoder) {
log.Debugf("toggle ziti on/off: %t", onOff)
state := rts.state
if onOff == state.Active {
log.Debug("nothing to do. the state of the tunnel already matches the requested state: %t", onOff)
respond(out, dto.Response{Message: fmt.Sprintf("noop: tunnel state already set to %t", onOff), Code: SUCCESS, Error: "", Payload: nil})
@@ -359,7 +401,7 @@ func tunnelState(onOff bool, out *json.Encoder) {
}
setTunnelState(onOff)
state.Active = onOff
runtime.SaveState(&state)
SaveState(&rts)
respond(out, dto.Response{Message: "tunnel state updated successfully", Code: SUCCESS, Error: "", Payload: nil})
log.Debugf("toggle ziti on/off: %t responded to", onOff)
@@ -367,8 +409,9 @@ func tunnelState(onOff bool, out *json.Encoder) {
func setTunnelState(onOff bool) {
if onOff {
runtime.TunStarted = time.Now()
TunStarted = time.Now()
state := rts.state
for _, id := range state.Identities {
connectIdentity(id)
}
@@ -380,7 +423,7 @@ func setTunnelState(onOff bool) {
func toggleIdentity(out *json.Encoder, fingerprint string, onOff bool) {
log.Debugf("toggle ziti on/off5 for %s: %t", fingerprint, onOff)
_, id := state.Find(fingerprint)
_, id := rts.Find(fingerprint)
if id.Active == onOff {
log.Debugf("nothing to do - the provided identity %s is already set to active=%t", id.Name, id.Active)
//nothing to do...
@@ -401,7 +444,7 @@ func toggleIdentity(out *json.Encoder, fingerprint string, onOff bool) {
respond(out, dto.Response{Message: "identity toggled", Code: SUCCESS, Error: "", Payload: idutil.Clean(*id)})
log.Debugf("toggle ziti on/off for %s: %t responded to", fingerprint, onOff)
runtime.SaveState(&state)
SaveState(&rts)
}
func removeTempFile(file os.File) {
@@ -495,16 +538,13 @@ func newIdentity(newId dto.AddIdentity, out *json.Encoder) {
log.Infof("enrolled successfully. identity file written to: %s", newPath)
connectIdentity(&newId.Id)
/*
if newId.Id.Active == true {
connectIdentity(&newId.Id)
}
*/
state := rts.state
//if successful parse the output and add the config to the identity
state.Identities = append(state.Identities, &newId.Id)
//save the state
runtime.SaveState(&state)
SaveState(&rts)
//return successful message
resp := dto.Response{Message: "success", Code: SUCCESS, Error: "", Payload: idutil.Clean(newId.Id)}
@@ -526,7 +566,7 @@ func connectIdentity(id *dto.Identity) {
if !id.Connected {
//tell the c sdk to use the file from the id and connect
log.Debugf("loading identity %s with fingerprint %s", id.Name, id.FingerPrint)
state.LoadIdentity(id)
rts.LoadIdentity(id)
} else {
log.Debugf("id [%s] is already connected - not reconnecting", id.Name)
}
@@ -558,7 +598,7 @@ func disconnectIdentity(id *dto.Identity) error {
func removeIdentity(out *json.Encoder, fingerprint string) {
log.Infof("request to remove identity by fingerprint: %s", fingerprint)
_, id := state.Find(fingerprint)
_, id := rts.Find(fingerprint)
if id == nil {
respondWithError(out, fmt.Sprintf("Could not find identity by fingerprint: %s", fingerprint), IDENTITY_NOT_FOUND, nil)
return
@@ -569,8 +609,8 @@ func removeIdentity(out *json.Encoder, fingerprint string) {
respondWithError(out, "Error when disconnecting identity", ERROR_DISCONNECTING_ID, err)
return
}
state.RemoveByIdentity(*id)
runtime.SaveState(&state)
rts.RemoveByIdentity(*id)
SaveState(&rts)
resp := dto.Response{Message: "success", Code: SUCCESS, Error: "", Payload: nil}
respond(out, resp)
@@ -578,5 +618,7 @@ func removeIdentity(out *json.Encoder, fingerprint string) {
}
func respond(out *json.Encoder, thing interface{}) {
//leave for debugging j := json.NewEncoder(os.Stdout)
//leave for debugging j.Encode(thing)
_ = out.Encode(thing)
}
@@ -1,4 +1,4 @@
package runtime
package service
import (
"time"
@@ -1,4 +1,4 @@
package runtime
package service
import (
"github.com/netfoundry/ziti-foundation/util/stringz"
+27 -7
View File
@@ -1,21 +1,21 @@
package service
import (
"github.com/tv42/topic"
"golang.org/x/sys/windows/svc"
"sync"
"wintun-testing/ziti-tunnel/globals"
"wintun-testing/ziti-tunnel/runtime"
)
var log = globals.Logger()
var pipeBase = `\\.\pipe\NetFoundry\tunneler\`
//var tunStatus = RuntimeState{}
var ipcPipeName = `\\.\pipe\NetFoundry\tunneler\ipc`
var logsPipeName = `\\.\pipe\NetFoundry\tunneler\logs`
var state = runtime.TunnelerState{}
//var state = dto.TunnelStatusa{}
var rts = RuntimeState{}
var interrupt chan struct{}
var wg sync.WaitGroup
var connections int
var Debug bool
const (
SUCCESS = 0
@@ -55,4 +55,24 @@ const (
System = "(A;;FA;;;SY)"
BuiltinAdmins = "(A;;FA;;;BA)"
LocalService = "(A;;FA;;;LS)"
)
)
func pipeName(path string) string {
if !Debug {
return pipeBase + path
} else {
return pipeBase + `debug\` + path
}
}
var top = topic.New()
func ipcPipeName() string {
return pipeName("ipc")
}
func logsPipeName() string {
return pipeName("logs")
}
func eventsPipeName() string {
return pipeName("events")
}
@@ -15,8 +15,7 @@ type zitiService struct{}
func (m *zitiService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
changes <- svc.Status{State: svc.StartPending}
log.Errorf("the main loop exited with an unexpected error: %v")
control := make(chan string)
control := make(chan string, 1)
mainLoop := make(chan struct{})
go func() {
err := SubMain(control, changes)
@@ -1,4 +1,4 @@
package runtime
package service
import (
"bufio"
@@ -11,54 +11,42 @@ import (
"strconv"
"time"
"wintun-testing/cziti"
"wintun-testing/ziti-tunnel/config"
"wintun-testing/ziti-tunnel/dto"
"wintun-testing/ziti-tunnel/idutil"
)
type TunnelerState struct {
Active bool
Duration int64
Identities []*dto.Identity
IpInfo *TunIpInfo `json:"IpInfo,omitempty"`
type RuntimeState struct {
state *dto.TunnelStatus
tun *tun.Device
tunName string
}
type TunIpInfo struct {
Ip string
Subnet string
MTU uint16
DNS string
}
func (t *TunnelerState) RemoveByFingerprint(fingerprint string) {
func (t *RuntimeState) RemoveByFingerprint(fingerprint string) {
log.Debugf("removing fingerprint: %s", fingerprint)
if index, _ := t.Find(fingerprint); index < len(t.Identities) {
t.Identities = append(t.Identities[:index], t.Identities[index+1:]...)
if index, _ := t.Find(fingerprint); index < len(t.state.Identities) {
t.state.Identities = append(t.state.Identities[:index], t.state.Identities[index+1:]...)
}
}
func (t *TunnelerState) Find(fingerprint string) (int, *dto.Identity) {
for i, n := range t.Identities {
func (t *RuntimeState) Find(fingerprint string) (int, *dto.Identity) {
for i, n := range t.state.Identities {
if n.FingerPrint == fingerprint {
return i, n
}
}
return len(t.Identities), nil
return len(t.state.Identities), nil
}
func (t *TunnelerState) RemoveByIdentity(id dto.Identity) {
func (t *RuntimeState) RemoveByIdentity(id dto.Identity) {
t.RemoveByFingerprint(id.FingerPrint)
}
func (t *TunnelerState) FindByIdentity(id dto.Identity) (int, *dto.Identity) {
func (t *RuntimeState) FindByIdentity(id dto.Identity) (int, *dto.Identity) {
return t.Find(id.FingerPrint)
}
func SaveState(s *TunnelerState) {
func SaveState(t *RuntimeState) {
// overwrite file if it exists
_ = os.MkdirAll(config.Path(), 0644)
@@ -69,8 +57,8 @@ func SaveState(s *TunnelerState) {
w := bufio.NewWriter(bufio.NewWriter(cfg))
enc := json.NewEncoder(w)
enc.SetIndent("", " ")
s.IpInfo = nil
_ = enc.Encode(s)
t.state.IpInfo = nil
_ = enc.Encode(t.state)
_ = w.Flush()
err = cfg.Close()
@@ -80,9 +68,9 @@ func SaveState(s *TunnelerState) {
log.Debug("state saved")
}
func (t *TunnelerState) Clean() TunnelerState {
func (t *RuntimeState) ToStatus() *dto.TunnelStatus {
var d int64
if t.Active {
if t.state.Active {
now := time.Now()
dd := now.Sub(TunStarted)
d = dd.Milliseconds()
@@ -90,21 +78,21 @@ func (t *TunnelerState) Clean() TunnelerState {
d = 0
}
rtn := TunnelerState{
Active: t.Active,
clean := dto.TunnelStatus{
Active: t.state.Active,
Duration: d,
Identities: make([]*dto.Identity, len(t.Identities)),
IpInfo: t.IpInfo,
Identities: make([]*dto.Identity, len(t.state.Identities)),
IpInfo: t.state.IpInfo,
}
for i, id := range t.Identities {
log.Debug("returning clean identity: %s", id.Name)
rtn.Identities[i] = idutil.Clean(*id)
for i, id := range t.state.Identities {
log.Debugf("returning clean identity: %s", id.Name)
clean.Identities[i] = idutil.Clean(*id)
}
return rtn
return &clean
}
func (t *TunnelerState) CreateTun() error {
func (t *RuntimeState) CreateTun() error {
if noZiti() {
log.Warnf("NOZITI set to true. this should be only used for debugging")
return nil
@@ -168,21 +156,7 @@ func (t *TunnelerState) CreateTun() error {
return nil
}
func (t *TunnelerState) Close() {
if t.tun != nil {
log.Warn("TODO: actually close the tun - or disable all the identities etc.")
/*
cziti.Stop()
*/
tu := *t.tun
err := tu.Close()
if err != nil {
log.Fatalf("problem closing tunnel!")
}
}
}
func (t *TunnelerState) LoadIdentity(id *dto.Identity) {
func (t *RuntimeState) LoadIdentity(id *dto.Identity) {
if !noZiti() {
if id.Connected {
log.Warnf("id [%s] already connected", id.FingerPrint)
@@ -221,3 +195,67 @@ func noZiti() bool {
v, _ := strconv.ParseBool(os.Getenv("NOZITI"))
return v
}
func (t *RuntimeState) Close() {
if t.tun != nil {
log.Warn("TODO: actually close the tun - or disable all the identities etc.")
/*
cziti.Stop()
*/
tu := *t.tun
err := tu.Close()
if err != nil {
log.Fatalf("problem closing tunnel!")
}
}
}
func (t *RuntimeState) LoadConfig() {
log.Debugf("reading config file located at: %s", config.File())
file, err := os.OpenFile(config.File(), os.O_RDONLY, 0644)
if err != nil {
t.state = &dto.TunnelStatus{}
return
}
r := bufio.NewReader(file)
dec := json.NewDecoder(r)
err = dec.Decode(&rts.state)
if err != nil {
log.Warnf("unexpected error reading config file. %v", err)
t.state = &dto.TunnelStatus{}
return
}
err = file.Close()
if err != nil {
log.Errorf("could not close configuration file. this is not normal! %v", err)
}
}