Jelajahi Sumber

Updated UI for stream proxy

Toby Chui 9 bulan lalu
induk
melakukan
d0c9a0148a
3 mengubah file dengan 434 tambahan dan 434 penghapusan
  1. 1 1
      main.go
  2. 430 430
      web/components/streamprox.html
  3. 3 3
      web/index.html

+ 1 - 1
main.go

@@ -54,7 +54,7 @@ var (
 	name        = "Zoraxy"
 	version     = "3.0.6"
 	nodeUUID    = "generic"
-	development = false //Set this to false to use embedded web fs
+	development = true //Set this to false to use embedded web fs
 	bootTime    = time.Now().Unix()
 
 	/*

+ 430 - 430
web/components/tcpprox.html → web/components/streamprox.html

@@ -1,431 +1,431 @@
-<div class="standardContainer">
-    <div class="ui basic segment">
-        <h2>TCP Proxy</h2>
-        <p>Proxy traffic flow on layer 3 via TCP/IP</p>
-    </div>
-    <div class="ui divider"></div>
-    <div class="ui basic segment" style="margin-top: 0;">
-        <h4>TCP Proxy Rules</h4>
-        <p>A list of TCP proxy rules created on this host. To enable them, use the toggle button on the right.</p>
-        <div style="overflow-x: auto; min-height: 400px;">
-            <table id="proxyTable" class="ui celled unstackable table">
-                <thead>
-                    <tr>
-                        <th>Name</th>
-                        <th>Port/Addr A</th>
-                        <th>Port/Addr B</th>
-                        <th>Mode</th>
-                        <th>Timeout (s)</th>
-                        <th>Actions</th>
-                    </tr>
-                </thead>
-                <tbody>
-
-                </tbody>
-            </table>
-        </div>
-        <button class="ui basic right floated button" onclick="initProxyConfigList();" title="Refresh List"><i class="ui green refresh icon"></i>Refresh</button>
-        <br><br>
-    </div>
-    <div class="ui divider"></div>
-    <div class="ui basic segment" id="addproxyConfig">
-        <h4>Add or Edit TCP Proxy</h4>
-        <p>Create or edit a new proxy instance</p>
-        <form id="tcpProxyForm" class="ui form">
-            <div class="field" style="display:none;">
-                <label>UUID</label>
-                <input type="text" name="uuid">
-            </div>
-            <div class="field">
-                <label>Name</label>
-                <input type="text" name="name" placeholder="Config Name">
-            </div>
-            <div class="field">
-                <label>Port A</label>
-                <input type="text" name="porta" placeholder="First address or port">
-            </div>
-                <div class="field">
-                <label>Port B</label>
-            <input type="text" name="portb" placeholder="Second address or port">
-            </div>
-            <div class="field">
-                <label>Timeout (s)</label>
-                <input type="text" name="timeout" placeholder="Timeout (s)">
-            </div>
-            <div class="field">
-                <label>Mode</label>
-                <select name="mode" class="ui dropdown">
-                    <option value="">Select Mode</option>
-                    <option value="listen">Listen</option>
-                    <option value="transport">Transport</option>
-                    <option value="starter">Starter</option>
-                </select>
-            </div>
-            <button id="addTcpProxyButton" class="ui basic button" type="submit"><i class="ui green add icon"></i> Create</button>  
-            <button id="editTcpProxyButton" class="ui basic button" onclick="confirmEditTCPProxyConfig(event);" style="display:none;"><i class="ui green check icon"></i> Update</button>  
-            <button class="ui basic red button" onclick="event.preventDefault(); cancelTCPProxyEdit(event);"><i class="ui red remove icon"></i> Cancel</button>  
-            <div class="ui basic inverted segment" style="background: var(--theme_background_inverted); border-radius: 0.6em;">
-                <p>TCP Proxy support the following TCP sockets proxy modes</p>
-                <table class="ui celled padded inverted basic table">
-                    <thead>
-                      <tr><th class="single line">Mode</th>
-                      <th>Public-IP</th>
-                      <th>Concurrent Access</th>
-                      <th>Flow Diagram</th>
-                    </tr></thead>
-                    <tbody>
-                      <tr>
-                        <td>
-                          <h4 class="ui center aligned inverted header">Transport</h4>
-                        </td>
-                        <td class="single line">
-                            Server: <i class="ui green check icon"></i><br>
-                            A: <i class="ui remove icon"></i><br>
-                            B: <i class="ui green check icon"></i> (or same LAN)<br>
-                        </td>
-                        <td>
-                            <i class="ui green check icon"></i>
-                        </td>
-                        <td>Port A (e.g. 25565) <i class="arrow right icon"></i> Server<br>
-                            Server <i class="arrow right icon"></i> Port B (e.g. 192.168.0.2:25565)<br>
-                            <small>Traffic from Port A will be forward to Port B's (IP if provided and) Port</small>
-                        </td>
-                      </tr>
-                      <tr>
-                        <td>
-                          <h4 class="ui center aligned inverted header">Listen</h4>
-                        </td>
-                        <td class="single line">
-                            Server: <i class="ui green check icon"></i><br>
-                            A: <i class="ui remove icon"></i><br>
-                            B: <i class="ui remove icon"></i><br>
-                        </td>
-                        <td>
-                            <i class="ui red times icon"></i>
-                        </td>
-                        <td>Port A (e.g. 8080) <i class="arrow right icon"></i> Server<br>
-                            Port B (e.g. 8081) <i class="arrow right icon"></i> Server<br>
-                            <small>Server will act as a bridge to proxy traffic between Port A and B</small>
-                        </td>
-                      </tr>
-                      <tr>
-                        <td>
-                          <h4 class="ui center aligned inverted header">Starter</h4>
-                        </td>
-                        <td class="single line">
-                            Server: <i class="ui times icon"></i><br>
-                            A: <i class="ui green check icon"></i><br>
-                            B: <i class="ui green check icon"></i><br>
-                        </td>
-                        <td>
-                            <i class="ui red times icon"></i>
-                        </td>
-                        <td>Server <i class="arrow right icon"></i> Port A (e.g. remote.local.:8080) <br>
-                            Server <i class="arrow right icon"></i> Port B (e.g. recv.local.:8081) <br>
-                            <small>Port A and B will be actively bridged</small>
-                        </td>
-                      </tr>
-                    </tbody>
-                  </table>
-                </div>
-        </form>
-    </div>
-</div>
-    <script>
-        let editingTCPProxyConfigUUID = ""; //The current editing TCP Proxy config UUID
-
-        $("#tcpProxyForm .dropdown").dropdown();
-        $('#tcpProxyForm').on('submit', function(event) {
-            event.preventDefault();
-
-            //Check if update mode
-            if ($("#editTcpProxyButton").is(":visible")){
-                confirmEditTCPProxyConfig(event);
-                return;
-            }
-
-            var form = $(this);
-
-            var formValid = validateTCPProxyConfig(form);
-            if (!formValid){
-                return;
-            }
-
-            // Send the AJAX POST request
-            $.ajax({
-                type: 'POST',
-                url: '/api/tcpprox/config/add',
-                data: form.serialize(),
-                success: function(response) {
-                    if (response.error) {
-                        msgbox(response.error, false, 6000);
-                    }else{
-                        msgbox("Config Added");
-                    }
-                    clearTCPProxyAddEditForm();
-                    initProxyConfigList();
-                    $("#addproxyConfig").slideUp("fast");
-                },
-                error: function() {
-                    msgbox('An error occurred while processing the request', false);
-                }
-            });
-        });
-            
-        function clearTCPProxyAddEditForm(){
-            $('#tcpProxyForm input, #tcpProxyForm select').val('');
-            $('#tcpProxyForm select').dropdown('clear');
-        }
-
-        function cancelTCPProxyEdit(event=undefined) {
-            clearTCPProxyAddEditForm();
-            $("#addTcpProxyButton").show();
-            $("#editTcpProxyButton").hide();
-        }
-
-        function validateTCPProxyConfig(form){
-            //Check if name is filled. If not, generate a random name for it
-            var name = form.find('input[name="name"]').val()
-            if (name == ""){
-                let randomName = "Proxy Rule (#" + Math.round(Date.now()/1000) + ")";
-                form.find('input[name="name"]').val(randomName);
-            }
-
-            // Validate timeout is an integer
-            var timeout = parseInt(form.find('input[name="timeout"]').val());
-            if (form.find('input[name="timeout"]').val() == ""){
-                //Not set. Assign a random one to it
-                form.find('input[name="timeout"]').val("10");
-                timeout = 10;
-            }
-            
-            if (isNaN(timeout)) {
-                form.find('input[name="timeout"]').parent().addClass("error");
-                msgbox('Timeout must be a valid integer', false, 5000);
-                return false;
-            }else{
-                form.find('input[name="timeout"]').parent().removeClass("error");
-            }
-
-            // Validate mode is selected
-            var mode = form.find('select[name="mode"]').val();
-            if (mode === '') {
-                form.find('select[name="mode"]').parent().addClass("error");
-                msgbox('Please select a mode', false, 5000);
-                return false;
-            }else{
-                form.find('select[name="mode"]').parent().removeClass("error");
-            }
-            return true;
-        }
-
-        function renderProxyConfigs(proxyConfigs) {
-            var tableBody = $('#proxyTable tbody');
-            tableBody.empty();
-            if (proxyConfigs.length === 0) {
-            var noResultsRow = $('<tr><td colspan="7"><i class="green check circle icon"></i>No Proxy Configs</td></tr>');
-                tableBody.append(noResultsRow);
-            } else {
-               
-                proxyConfigs.forEach(function(config) {
-                    var runningLogo = 'Stopped';
-                    var runningClass = "stopped";
-                    var startButton = `<button onclick="startTcpProx('${config.UUID}');" class="ui button" title="Start Proxy"><i class="green play icon"></i> Start Proxy</button>`;
-                    if (config.Running){
-                        runningLogo = 'Running';
-                        startButton = `<button onclick="stopTcpProx('${config.UUID}');" class="ui button" title="Start Proxy"><i class="red stop icon"></i> Stop Proxy</button>`;
-                        runningClass = "running"
-                    }
-
-                    var modeText = "Unknown";
-                    if (config.Mode == 0){
-                        modeText = "Listen";
-                    }else if (config.Mode == 1){
-                        modeText = "Transport";
-                    }else if (config.Mode == 2){
-                        modeText = "Starter";
-                    }
-
-                    var thisConfig = encodeURIComponent(JSON.stringify(config));
-
-                    var row = $(`<tr class="tcproxConfig ${runningClass}" uuid="${config.UUID}" config="${thisConfig}">`);
-                    row.append($('<td>').html(`
-                        ${config.Name}
-                        <div class="statusText">${runningLogo}</div>`));
-                    row.append($('<td>').text(config.PortA));
-                    row.append($('<td>').text(config.PortB));
-                    row.append($('<td>').text(modeText));
-                    row.append($('<td>').text(config.Timeout));
-                    row.append($('<td>').html(`
-                        <div class="ui basic vertical fluid tiny buttons">
-                            <button class="ui button" onclick="validateProxyConfig('${config.UUID}', this);" title="Validate Config"><i class="teal question circle outline icon"></i> CXN Test</button>
-                            ${startButton}
-                            <button onclick="editTCPProxyConfig('${config.UUID}');" class="ui button" title="Edit Config"><i class="edit icon"></i> Edit </button>
-                            <button onclick="deleteTCPProxyConfig('${config.UUID}');" class="ui red basic button" title="Delete Config"><i class="trash icon"></i> Remove</button>
-                        </div>
-                    `));
-                    tableBody.append(row);
-                });
-            }
-        }
-
-        function getConfigDetailsFromDOM(configUUID){
-            let thisConfig = null;
-            $(".tcproxConfig").each(function(){
-                let uuid = $(this).attr("uuid");
-                if (configUUID == uuid){
-                    //This is the one we are looking for
-                    thisConfig = JSON.parse(decodeURIComponent($(this).attr("config")));
-                }
-            });
-            return thisConfig;
-        }   
-
-        function validateProxyConfig(configUUID, btn){
-            $(btn).html(`<i class="ui loading spinner icon"></i>`);
-            $.ajax({
-                url: "/api/tcpprox/config/validate",
-                data: {uuid: configUUID},
-                success: function(data){
-                    if (data.error != undefined){
-                        let errormsg = data.error.charAt(0).toUpperCase() + data.error.slice(1);
-                        $(btn).html(`<i class="red times icon"></i> ${errormsg}`);
-                        msgbox(data.error, false, 6000);
-                    }else{
-                        $(btn).html(`<i class="green check icon"></i> Config Valid`);
-                        msgbox("Config Check Passed");
-                    }
-                }
-            })   
-        }
-
-        function editTCPProxyConfig(configUUID){
-            let targetConfig = getConfigDetailsFromDOM(configUUID);
-            if (targetConfig != null){
-                $("#addTcpProxyButton").hide();
-                $("#editTcpProxyButton").show();
-               $.each(targetConfig, function(key, value) {
-                    var field = $("#tcpProxyForm").find('[name="' + key.toLowerCase() + '"]');
-                    if (field.length > 0) {
-                        if (field.is('input')) {
-                            field.val(value);
-                        }else if (field.is('select')){
-                            if (key.toLowerCase() == "mode"){
-                                if (value == 0){
-                                    value = "listen";
-                                }else if (value == 1){
-                                    value = "transport";
-                                }else if (value == 2){
-                                    value = "starter";
-                                }
-                            }
-                            $(field).dropdown("set selected", value);
-                        }
-                    }
-                });
-                editingTCPProxyConfigUUID = configUUID;
-                $("#addproxyConfig").slideDown("fast");
-
-            }else{
-                msgbox("Unable to load target config", false);
-            }
-        }
-
-        function confirmEditTCPProxyConfig(event){
-            event.preventDefault();
-            event.stopImmediatePropagation();
-            var form = $("#tcpProxyForm");
-
-            var formValid = validateTCPProxyConfig(form);
-            if (!formValid){
-                return;
-            }
-
-            // Send the AJAX POST request
-            $.ajax({
-                type: 'POST',
-                url: '/api/tcpprox/config/edit',
-                data: form.serialize(),
-                success: function(response) {
-                    if (response.error) {
-                        msgbox(response.error, false, 6000);
-                    }else{
-                        msgbox("Config Updated");
-                    }
-                    initProxyConfigList();
-                    cancelTCPProxyEdit();
-                    
-                },
-                error: function() {
-                    msgbox('An error occurred while processing the request', false);
-                }
-            });
-        }
-
-        function deleteTCPProxyConfig(configUUID){
-            $.ajax({
-                url: "/api/tcpprox/config/delete",
-                method: "POST",
-                data: {uuid: configUUID},
-                success: function(data){
-                    if (data.error != undefined){
-                        msgbox(data.error, false, 6000);
-                    }else{
-                        msgbox("Proxy Config Removed");
-                        initProxyConfigList();
-                    }
-                }
-            })
-        }
-
-        //Start a TCP proxy by their config UUID
-        function startTcpProx(configUUID){
-            $.ajax({
-                url: "/api/tcpprox/config/start",
-                method: "POST",
-                data: {uuid: configUUID},
-                success: function(data){
-                    if (data.error != undefined){
-                        msgbox(data.error, false, 6000);
-                    }else{
-                        msgbox("Service Started");
-                        initProxyConfigList();
-                    }
-                }
-
-            });
-        }
-
-        //Stop a TCP proxy by their config UUID
-        function stopTcpProx(configUUID){
-            $.ajax({
-                url: "/api/tcpprox/config/stop",
-                method: "POST",
-                data: {uuid: configUUID},
-                success: function(data){
-                    if (data.error != undefined){
-                        msgbox(data.error, false, 6000);
-                    }else{
-                        msgbox("Service Stopped");
-                        initProxyConfigList();
-                    }
-                }
-
-            });
-        }
-
-        function initProxyConfigList(){
-            $.ajax({
-                type: 'GET',
-                url: '/api/tcpprox/config/list',
-                success: function(response) {
-                    renderProxyConfigs(response);
-                },
-                error: function() {
-                    msgbox('Unable to load proxy configs', false);
-                }
-            });
-        }
-        initProxyConfigList();
-    </script>
+<div class="standardContainer">
+    <div class="ui basic segment">
+        <h2>Stream Proxy</h2>
+        <p>Proxy traffic flow on layer 3 via TCP or UDP</p>
+    </div>
+    <div class="ui divider"></div>
+    <div class="ui basic segment" style="margin-top: 0;">
+        <h4>TCP / UDP Proxy Rules</h4>
+        <p>A list of TCP proxy rules created on this host. To enable them, use the toggle button on the right.</p>
+        <div style="overflow-x: auto; min-height: 400px;">
+            <table id="proxyTable" class="ui celled unstackable table">
+                <thead>
+                    <tr>
+                        <th>Name</th>
+                        <th>Port/Addr A</th>
+                        <th>Port/Addr B</th>
+                        <th>Mode</th>
+                        <th>Timeout (s)</th>
+                        <th>Actions</th>
+                    </tr>
+                </thead>
+                <tbody>
+
+                </tbody>
+            </table>
+        </div>
+        <button class="ui basic right floated button" onclick="initProxyConfigList();" title="Refresh List"><i class="ui green refresh icon"></i>Refresh</button>
+        <br><br>
+    </div>
+    <div class="ui divider"></div>
+    <div class="ui basic segment" id="addproxyConfig">
+        <h4>Add or Edit TCP Proxy</h4>
+        <p>Create or edit a new proxy instance</p>
+        <form id="tcpProxyForm" class="ui form">
+            <div class="field" style="display:none;">
+                <label>UUID</label>
+                <input type="text" name="uuid">
+            </div>
+            <div class="field">
+                <label>Name</label>
+                <input type="text" name="name" placeholder="Config Name">
+            </div>
+            <div class="field">
+                <label>Port A</label>
+                <input type="text" name="porta" placeholder="First address or port">
+            </div>
+                <div class="field">
+                <label>Port B</label>
+            <input type="text" name="portb" placeholder="Second address or port">
+            </div>
+            <div class="field">
+                <label>Timeout (s)</label>
+                <input type="text" name="timeout" placeholder="Timeout (s)">
+            </div>
+            <div class="field">
+                <label>Mode</label>
+                <select name="mode" class="ui dropdown">
+                    <option value="">Select Mode</option>
+                    <option value="listen">Listen</option>
+                    <option value="transport">Transport</option>
+                    <option value="starter">Starter</option>
+                </select>
+            </div>
+            <button id="addTcpProxyButton" class="ui basic button" type="submit"><i class="ui green add icon"></i> Create</button>  
+            <button id="editTcpProxyButton" class="ui basic button" onclick="confirmEditTCPProxyConfig(event);" style="display:none;"><i class="ui green check icon"></i> Update</button>  
+            <button class="ui basic red button" onclick="event.preventDefault(); cancelTCPProxyEdit(event);"><i class="ui red remove icon"></i> Cancel</button>  
+            <div class="ui basic inverted segment" style="background: var(--theme_background_inverted); border-radius: 0.6em;">
+                <p>TCP Proxy support the following TCP sockets proxy modes</p>
+                <table class="ui celled padded inverted basic table">
+                    <thead>
+                      <tr><th class="single line">Mode</th>
+                      <th>Public-IP</th>
+                      <th>Concurrent Access</th>
+                      <th>Flow Diagram</th>
+                    </tr></thead>
+                    <tbody>
+                      <tr>
+                        <td>
+                          <h4 class="ui center aligned inverted header">Transport</h4>
+                        </td>
+                        <td class="single line">
+                            Server: <i class="ui green check icon"></i><br>
+                            A: <i class="ui remove icon"></i><br>
+                            B: <i class="ui green check icon"></i> (or same LAN)<br>
+                        </td>
+                        <td>
+                            <i class="ui green check icon"></i>
+                        </td>
+                        <td>Port A (e.g. 25565) <i class="arrow right icon"></i> Server<br>
+                            Server <i class="arrow right icon"></i> Port B (e.g. 192.168.0.2:25565)<br>
+                            <small>Traffic from Port A will be forward to Port B's (IP if provided and) Port</small>
+                        </td>
+                      </tr>
+                      <tr>
+                        <td>
+                          <h4 class="ui center aligned inverted header">Listen</h4>
+                        </td>
+                        <td class="single line">
+                            Server: <i class="ui green check icon"></i><br>
+                            A: <i class="ui remove icon"></i><br>
+                            B: <i class="ui remove icon"></i><br>
+                        </td>
+                        <td>
+                            <i class="ui red times icon"></i>
+                        </td>
+                        <td>Port A (e.g. 8080) <i class="arrow right icon"></i> Server<br>
+                            Port B (e.g. 8081) <i class="arrow right icon"></i> Server<br>
+                            <small>Server will act as a bridge to proxy traffic between Port A and B</small>
+                        </td>
+                      </tr>
+                      <tr>
+                        <td>
+                          <h4 class="ui center aligned inverted header">Starter</h4>
+                        </td>
+                        <td class="single line">
+                            Server: <i class="ui times icon"></i><br>
+                            A: <i class="ui green check icon"></i><br>
+                            B: <i class="ui green check icon"></i><br>
+                        </td>
+                        <td>
+                            <i class="ui red times icon"></i>
+                        </td>
+                        <td>Server <i class="arrow right icon"></i> Port A (e.g. remote.local.:8080) <br>
+                            Server <i class="arrow right icon"></i> Port B (e.g. recv.local.:8081) <br>
+                            <small>Port A and B will be actively bridged</small>
+                        </td>
+                      </tr>
+                    </tbody>
+                  </table>
+                </div>
+        </form>
+    </div>
+</div>
+    <script>
+        let editingTCPProxyConfigUUID = ""; //The current editing TCP Proxy config UUID
+
+        $("#tcpProxyForm .dropdown").dropdown();
+        $('#tcpProxyForm').on('submit', function(event) {
+            event.preventDefault();
+
+            //Check if update mode
+            if ($("#editTcpProxyButton").is(":visible")){
+                confirmEditTCPProxyConfig(event);
+                return;
+            }
+
+            var form = $(this);
+
+            var formValid = validateTCPProxyConfig(form);
+            if (!formValid){
+                return;
+            }
+
+            // Send the AJAX POST request
+            $.ajax({
+                type: 'POST',
+                url: '/api/tcpprox/config/add',
+                data: form.serialize(),
+                success: function(response) {
+                    if (response.error) {
+                        msgbox(response.error, false, 6000);
+                    }else{
+                        msgbox("Config Added");
+                    }
+                    clearTCPProxyAddEditForm();
+                    initProxyConfigList();
+                    $("#addproxyConfig").slideUp("fast");
+                },
+                error: function() {
+                    msgbox('An error occurred while processing the request', false);
+                }
+            });
+        });
+            
+        function clearTCPProxyAddEditForm(){
+            $('#tcpProxyForm input, #tcpProxyForm select').val('');
+            $('#tcpProxyForm select').dropdown('clear');
+        }
+
+        function cancelTCPProxyEdit(event=undefined) {
+            clearTCPProxyAddEditForm();
+            $("#addTcpProxyButton").show();
+            $("#editTcpProxyButton").hide();
+        }
+
+        function validateTCPProxyConfig(form){
+            //Check if name is filled. If not, generate a random name for it
+            var name = form.find('input[name="name"]').val()
+            if (name == ""){
+                let randomName = "Proxy Rule (#" + Math.round(Date.now()/1000) + ")";
+                form.find('input[name="name"]').val(randomName);
+            }
+
+            // Validate timeout is an integer
+            var timeout = parseInt(form.find('input[name="timeout"]').val());
+            if (form.find('input[name="timeout"]').val() == ""){
+                //Not set. Assign a random one to it
+                form.find('input[name="timeout"]').val("10");
+                timeout = 10;
+            }
+            
+            if (isNaN(timeout)) {
+                form.find('input[name="timeout"]').parent().addClass("error");
+                msgbox('Timeout must be a valid integer', false, 5000);
+                return false;
+            }else{
+                form.find('input[name="timeout"]').parent().removeClass("error");
+            }
+
+            // Validate mode is selected
+            var mode = form.find('select[name="mode"]').val();
+            if (mode === '') {
+                form.find('select[name="mode"]').parent().addClass("error");
+                msgbox('Please select a mode', false, 5000);
+                return false;
+            }else{
+                form.find('select[name="mode"]').parent().removeClass("error");
+            }
+            return true;
+        }
+
+        function renderProxyConfigs(proxyConfigs) {
+            var tableBody = $('#proxyTable tbody');
+            tableBody.empty();
+            if (proxyConfigs.length === 0) {
+            var noResultsRow = $('<tr><td colspan="7"><i class="green check circle icon"></i>No Proxy Configs</td></tr>');
+                tableBody.append(noResultsRow);
+            } else {
+               
+                proxyConfigs.forEach(function(config) {
+                    var runningLogo = 'Stopped';
+                    var runningClass = "stopped";
+                    var startButton = `<button onclick="startTcpProx('${config.UUID}');" class="ui button" title="Start Proxy"><i class="green play icon"></i> Start Proxy</button>`;
+                    if (config.Running){
+                        runningLogo = 'Running';
+                        startButton = `<button onclick="stopTcpProx('${config.UUID}');" class="ui button" title="Start Proxy"><i class="red stop icon"></i> Stop Proxy</button>`;
+                        runningClass = "running"
+                    }
+
+                    var modeText = "Unknown";
+                    if (config.Mode == 0){
+                        modeText = "Listen";
+                    }else if (config.Mode == 1){
+                        modeText = "Transport";
+                    }else if (config.Mode == 2){
+                        modeText = "Starter";
+                    }
+
+                    var thisConfig = encodeURIComponent(JSON.stringify(config));
+
+                    var row = $(`<tr class="tcproxConfig ${runningClass}" uuid="${config.UUID}" config="${thisConfig}">`);
+                    row.append($('<td>').html(`
+                        ${config.Name}
+                        <div class="statusText">${runningLogo}</div>`));
+                    row.append($('<td>').text(config.PortA));
+                    row.append($('<td>').text(config.PortB));
+                    row.append($('<td>').text(modeText));
+                    row.append($('<td>').text(config.Timeout));
+                    row.append($('<td>').html(`
+                        <div class="ui basic vertical fluid tiny buttons">
+                            <button class="ui button" onclick="validateProxyConfig('${config.UUID}', this);" title="Validate Config"><i class="teal question circle outline icon"></i> CXN Test</button>
+                            ${startButton}
+                            <button onclick="editTCPProxyConfig('${config.UUID}');" class="ui button" title="Edit Config"><i class="edit icon"></i> Edit </button>
+                            <button onclick="deleteTCPProxyConfig('${config.UUID}');" class="ui red basic button" title="Delete Config"><i class="trash icon"></i> Remove</button>
+                        </div>
+                    `));
+                    tableBody.append(row);
+                });
+            }
+        }
+
+        function getConfigDetailsFromDOM(configUUID){
+            let thisConfig = null;
+            $(".tcproxConfig").each(function(){
+                let uuid = $(this).attr("uuid");
+                if (configUUID == uuid){
+                    //This is the one we are looking for
+                    thisConfig = JSON.parse(decodeURIComponent($(this).attr("config")));
+                }
+            });
+            return thisConfig;
+        }   
+
+        function validateProxyConfig(configUUID, btn){
+            $(btn).html(`<i class="ui loading spinner icon"></i>`);
+            $.ajax({
+                url: "/api/tcpprox/config/validate",
+                data: {uuid: configUUID},
+                success: function(data){
+                    if (data.error != undefined){
+                        let errormsg = data.error.charAt(0).toUpperCase() + data.error.slice(1);
+                        $(btn).html(`<i class="red times icon"></i> ${errormsg}`);
+                        msgbox(data.error, false, 6000);
+                    }else{
+                        $(btn).html(`<i class="green check icon"></i> Config Valid`);
+                        msgbox("Config Check Passed");
+                    }
+                }
+            })   
+        }
+
+        function editTCPProxyConfig(configUUID){
+            let targetConfig = getConfigDetailsFromDOM(configUUID);
+            if (targetConfig != null){
+                $("#addTcpProxyButton").hide();
+                $("#editTcpProxyButton").show();
+               $.each(targetConfig, function(key, value) {
+                    var field = $("#tcpProxyForm").find('[name="' + key.toLowerCase() + '"]');
+                    if (field.length > 0) {
+                        if (field.is('input')) {
+                            field.val(value);
+                        }else if (field.is('select')){
+                            if (key.toLowerCase() == "mode"){
+                                if (value == 0){
+                                    value = "listen";
+                                }else if (value == 1){
+                                    value = "transport";
+                                }else if (value == 2){
+                                    value = "starter";
+                                }
+                            }
+                            $(field).dropdown("set selected", value);
+                        }
+                    }
+                });
+                editingTCPProxyConfigUUID = configUUID;
+                $("#addproxyConfig").slideDown("fast");
+
+            }else{
+                msgbox("Unable to load target config", false);
+            }
+        }
+
+        function confirmEditTCPProxyConfig(event){
+            event.preventDefault();
+            event.stopImmediatePropagation();
+            var form = $("#tcpProxyForm");
+
+            var formValid = validateTCPProxyConfig(form);
+            if (!formValid){
+                return;
+            }
+
+            // Send the AJAX POST request
+            $.ajax({
+                type: 'POST',
+                url: '/api/tcpprox/config/edit',
+                data: form.serialize(),
+                success: function(response) {
+                    if (response.error) {
+                        msgbox(response.error, false, 6000);
+                    }else{
+                        msgbox("Config Updated");
+                    }
+                    initProxyConfigList();
+                    cancelTCPProxyEdit();
+                    
+                },
+                error: function() {
+                    msgbox('An error occurred while processing the request', false);
+                }
+            });
+        }
+
+        function deleteTCPProxyConfig(configUUID){
+            $.ajax({
+                url: "/api/tcpprox/config/delete",
+                method: "POST",
+                data: {uuid: configUUID},
+                success: function(data){
+                    if (data.error != undefined){
+                        msgbox(data.error, false, 6000);
+                    }else{
+                        msgbox("Proxy Config Removed");
+                        initProxyConfigList();
+                    }
+                }
+            })
+        }
+
+        //Start a TCP proxy by their config UUID
+        function startTcpProx(configUUID){
+            $.ajax({
+                url: "/api/tcpprox/config/start",
+                method: "POST",
+                data: {uuid: configUUID},
+                success: function(data){
+                    if (data.error != undefined){
+                        msgbox(data.error, false, 6000);
+                    }else{
+                        msgbox("Service Started");
+                        initProxyConfigList();
+                    }
+                }
+
+            });
+        }
+
+        //Stop a TCP proxy by their config UUID
+        function stopTcpProx(configUUID){
+            $.ajax({
+                url: "/api/tcpprox/config/stop",
+                method: "POST",
+                data: {uuid: configUUID},
+                success: function(data){
+                    if (data.error != undefined){
+                        msgbox(data.error, false, 6000);
+                    }else{
+                        msgbox("Service Stopped");
+                        initProxyConfigList();
+                    }
+                }
+
+            });
+        }
+
+        function initProxyConfigList(){
+            $.ajax({
+                type: 'GET',
+                url: '/api/tcpprox/config/list',
+                success: function(response) {
+                    renderProxyConfigs(response);
+                },
+                error: function() {
+                    msgbox('Unable to load proxy configs', false);
+                }
+            });
+        }
+        initProxyConfigList();
+    </script>
 </div>

+ 3 - 3
web/index.html

@@ -52,8 +52,8 @@
                     <a class="item" tag="rules">
                         <i class="simplistic plus square icon"></i> Create Proxy Rules
                     </a>
-                    <a class="item" tag="tcpprox">
-                        <i class="simplistic exchange icon"></i> TCP Proxy
+                    <a class="item" tag="streamproxy">
+                        <i class="simplistic exchange icon"></i> Stream Proxy
                     </a>
                     <div class="ui divider menudivider">Access & Connections</div>
                     <a class="item" tag="cert">
@@ -125,7 +125,7 @@
                 <div id="zgrok" class="functiontab" target="zgrok.html"></div>
 
                 <!-- TCP Proxy -->
-                <div id="tcpprox" class="functiontab" target="tcpprox.html"></div>
+                <div id="streamproxy" class="functiontab" target="streamprox.html"></div>
 
                 <!-- Web Server -->
                 <div id="webserv" class="functiontab" target="webserv.html"></div>