"))
39 | {
40 | try
41 | {
42 | var evt = Event.Parse(match.Value);
43 | Log.Information($"server=wss endpoint={Socket.RemoteEndPoint} session={Id} event=cot uid={evt.Uid} type={evt.Type}");
44 | _router.Send(evt, null);
45 | }
46 | catch (Exception e)
47 | {
48 | Log.Error($"server=wss endpoint={Socket.RemoteEndPoint} session={Id} type=unknown error=true forwarded=false message=\"{e.Message}\"");
49 | }
50 | }
51 | }
52 | catch (Exception e)
53 | {
54 | Log.Error($"server=wss endpoint={Socket.RemoteEndPoint} session={Id} type=unknown error=true forwarded=false message=\"{e.Message}\"");
55 | }
56 | }
57 |
58 | protected override void OnError(SocketError error)
59 | {
60 | Log.Error($"server=wss endpoint={Socket.RemoteEndPoint} session={Id} error=true message=\"{error}\"");
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/Home/Clients.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Clients";
3 | }
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Callsign |
13 | Device |
14 | Platform |
15 | Version |
16 | LastSeen |
17 | |
18 |
19 |
20 |
21 | @foreach (var client in ViewData["clients"] as IEnumerable)
22 | {
23 |
24 | @client.Callsign |
25 | @client.Device |
26 | @client.Platform |
27 | @client.Version |
28 | @client.LastSeen.ToUniversalTime().ToString("u") |
29 |
30 |
31 |
36 | |
37 |
38 | }
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/Home/DataPackages.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Data Packages";
3 | }
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Id
15 | |
16 |
17 | Name
18 | |
19 |
20 | Timestamp
21 | |
22 |
23 | Uploader
24 | |
25 |
26 | Size
27 | |
28 |
29 |
30 | |
31 |
32 |
33 |
34 | @foreach (var package in ViewData["datapackages"] as IEnumerable)
35 | {
36 |
37 | @package.UID |
38 | @package.Name |
39 | @package.SubmissionDateTime.ToUniversalTime().ToString("u") |
40 | @package.SubmissionUser |
41 | @package.Size |
42 |
43 |
44 |
45 |
46 |
47 | Download
48 |
49 |
50 |
55 | |
56 |
57 | }
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/Home/Index.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Home Page";
3 |
4 | var devicesCount = 12;
5 | var usersCount = 34;
6 | var datapackagesCount = 56;
7 | var eventsCount = 78;
8 | }
9 |
10 |
11 |
62 |
63 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/Home/Map.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | ViewData["Title"] = "Map";
3 | }
4 | @section Styles {
5 |
6 |
9 | }
10 |
11 |
14 |
15 | @section Scripts {
16 |
17 |
18 |
90 | }
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/Shared/Error.cshtml:
--------------------------------------------------------------------------------
1 | @model ErrorViewModel
2 | @{
3 | ViewData["Title"] = "Error";
4 | }
5 |
6 | Error.
7 | An error occurred while processing your request.
8 |
9 | @if (Model.ShowRequestId)
10 | {
11 |
12 | Request ID: @Model.RequestId
13 |
14 | }
15 |
16 | Development Mode
17 |
18 | Swapping to Development environment will display more detailed information about the error that occurred.
19 |
20 |
21 | The Development environment shouldn't be enabled for deployed applications.
22 | It can result in displaying sensitive information from exceptions to end users.
23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
24 | and restarting the app.
25 |
26 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/Shared/_Layout.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | @ViewData["Title"] - OpenTakRouter
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | @await RenderSectionAsync("Styles", required: false)
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | @RenderBody()
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | @await RenderSectionAsync("Scripts", required: false)
62 |
63 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/Shared/_MainNavigation.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/Shared/_ValidationScriptsPartial.cshtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/_ViewImports.cshtml:
--------------------------------------------------------------------------------
1 | @using dpp.opentakrouter
2 | @using dpp.opentakrouter.Models
3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
4 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/Views/_ViewStart.cshtml:
--------------------------------------------------------------------------------
1 | @{
2 | Layout = "_Layout";
3 | }
4 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/WebConfig.cs:
--------------------------------------------------------------------------------
1 | namespace dpp.opentakrouter
2 | {
3 | public class WebConfig
4 | {
5 | public bool Enabled { get; set; } = true;
6 | public int? Port { get; set; }
7 | public bool Swagger { get; set; } = true;
8 | public bool Ssl { get; set; } = false;
9 | public string Cert { get; set; } = "";
10 | public string Passphrase { get; set; } = "";
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/WebService.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.AspNetCore.Builder;
2 | using Microsoft.Extensions.Configuration;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using Microsoft.OpenApi.Models;
5 | using Serilog;
6 |
7 | namespace dpp.opentakrouter
8 | {
9 | public class WebService
10 | {
11 | public IConfiguration Configuration { get; }
12 | public WebService(IConfiguration configuration)
13 | {
14 | Configuration = configuration;
15 | }
16 |
17 | // This method gets called by the runtime. Use this method to add services to the container.
18 | public void ConfigureServices(IServiceCollection services)
19 | {
20 | services.AddControllersWithViews();
21 | services.AddSwaggerGen(c =>
22 | {
23 | c.SwaggerDoc("v1", new OpenApiInfo { Title = "OpenTakRouter", Version = "v1" });
24 | });
25 | }
26 |
27 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
28 | public void Configure(IApplicationBuilder app)
29 | {
30 | var apiConfig = Configuration.GetSection("server:api").Get();
31 | if (apiConfig is not null)
32 | {
33 | if (apiConfig.Swagger)
34 | {
35 | app.UseSwagger();
36 | app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "OpenTakRouter v1"));
37 | }
38 |
39 | if (apiConfig.Ssl)
40 | {
41 | app.UseHttpsRedirection();
42 | }
43 | }
44 |
45 | app.UseStaticFiles();
46 | app.UseSerilogRequestLogging(options =>
47 | {
48 | options.MessageTemplate = "server=web endpoint={RemoteIpAddress} method={RequestMethod} req={RequestPath} status={StatusCode} ms={Elapsed}";
49 | options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
50 | {
51 | diagnosticContext.Set("RemoteIpAddress", httpContext.Connection.RemoteIpAddress);
52 | };
53 | });
54 | app.UseRouting();
55 | app.UseAuthorization();
56 | app.UseEndpoints(endpoints =>
57 | {
58 | endpoints.MapControllers();
59 | });
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/dpp.opentakrouter.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | 1.0.16
7 | 1.0.16.0
8 |
9 | win-x64;linux-x64;linux-arm64
10 | opentakrouter
11 | Linux
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | PreserveNewest
38 |
39 |
40 |
41 |
42 |
43 | PreserveNewest
44 | true
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/libman.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.0",
3 | "defaultProvider": "cdnjs",
4 | "libraries": [
5 | {
6 | "library": "jquery@3.6.0",
7 | "destination": "wwwroot/lib/jquery/"
8 | },
9 | {
10 | "library": "bootstrap@5.1.3",
11 | "destination": "wwwroot/lib/bootstrap/"
12 | },
13 | {
14 | "library": "admin-lte@3.2.0",
15 | "destination": "wwwroot/lib/admin-lte/"
16 | },
17 | {
18 | "library": "font-awesome@6.1.1",
19 | "destination": "wwwroot/lib/font-awesome/"
20 | },
21 | {
22 | "provider": "jsdelivr",
23 | "library": "@fontsource/source-sans-pro@4.5.6",
24 | "destination": "wwwroot/lib/fontsource"
25 | },
26 | {
27 | "library": "leaflet@1.7.1",
28 | "destination": "wwwroot/lib/leaflet/"
29 | },
30 | {
31 | "provider": "jsdelivr",
32 | "library": "milsymbol@2.0.0",
33 | "destination": "wwwroot/lib/milsymbol/"
34 | }
35 | ]
36 | }
--------------------------------------------------------------------------------
/dpp.opentakrouter/opentakrouter.json:
--------------------------------------------------------------------------------
1 | {
2 | "AllowedHosts": "*",
3 | "server": {
4 | // the data directory where the database file is located.
5 | // defaults to the executable location.
6 | //"data": "%appdata%/opentakrouter",
7 |
8 | // persist messages to the local database. on by default.
9 | // in extreme cases this may increase throughput slightly.
10 | "persist_messages": true,
11 |
12 | // set the server name. this is used for api/federation functionality.
13 | // defaults to the hostname.
14 | //"name": ""
15 |
16 | // the api interface configuration
17 | "api": {
18 | "port": 8080,
19 | "swagger": true,
20 |
21 | "ssl": false,
22 | "cert": "server.p12",
23 | "passphrase": "atakatak"
24 | },
25 | "websockets": {
26 | "enabled": true,
27 | "port": 5000,
28 |
29 | "ssl": false,
30 | "cert": "server.p12",
31 | "passphrase": "atakatak"
32 | },
33 |
34 | // the tak protocol configurations
35 | "tak": {
36 | "tcp": {
37 | "enabled": true,
38 | "port": 58087
39 | },
40 | "tls": {
41 | "enabled": false,
42 | "port": 58089,
43 | "cert": "server.p12",
44 | "passphrase": "atakatak"
45 | }
46 | },
47 | "peers": [
48 | ]
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/wwwroot/css/site.css:
--------------------------------------------------------------------------------
1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
2 | for details on configuring this project to bundle and minify static web assets. */
3 |
4 | a.navbar-brand {
5 | white-space: normal;
6 | text-align: center;
7 | word-break: break-all;
8 | }
9 |
10 | /* Provide sufficient contrast against white background */
11 | a {
12 | color: #0366d6;
13 | }
14 |
15 | .btn-primary {
16 | color: #fff;
17 | background-color: #1b6ec2;
18 | border-color: #1861ac;
19 | }
20 |
21 | .nav-pills .nav-link.active, .nav-pills .show > .nav-link {
22 | color: #fff;
23 | background-color: #1b6ec2;
24 | border-color: #1861ac;
25 | }
26 |
27 | /* Sticky footer styles
28 | -------------------------------------------------- */
29 | html {
30 | font-size: 14px;
31 | }
32 | @media (min-width: 768px) {
33 | html {
34 | font-size: 16px;
35 | }
36 | }
37 |
38 | .border-top {
39 | border-top: 1px solid #e5e5e5;
40 | }
41 | .border-bottom {
42 | border-bottom: 1px solid #e5e5e5;
43 | }
44 |
45 | .box-shadow {
46 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
47 | }
48 |
49 | button.accept-policy {
50 | font-size: 1rem;
51 | line-height: inherit;
52 | }
53 |
54 | /* Sticky footer styles
55 | -------------------------------------------------- */
56 | html {
57 | position: relative;
58 | min-height: 100%;
59 | }
60 |
61 | body {
62 | /* Margin bottom by footer height */
63 | margin-bottom: 60px;
64 | }
65 | .footer {
66 | position: absolute;
67 | bottom: 0;
68 | width: 100%;
69 | white-space: nowrap;
70 | line-height: 60px; /* Vertically center the text there */
71 | }
72 |
--------------------------------------------------------------------------------
/dpp.opentakrouter/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/darkplusplus/opentakrouter/b361860fad1ad0a913331a555f651f95fe6cf6c6/dpp.opentakrouter/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/dpp.opentakrouter/wwwroot/js/site.js:
--------------------------------------------------------------------------------
1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
2 | // for details on configuring this project to bundle and minify static web assets.
3 |
4 | // Write your JavaScript code.
5 |
--------------------------------------------------------------------------------
/opentakrouter.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.6.30114.105
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dpp.opentakrouter", "dpp.opentakrouter\dpp.opentakrouter.csproj", "{73115B5B-9E47-4D60-A3F8-5F92F55D15EA}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dpp.opentakrouter.Tests", "dpp.opentakrouter.Tests\dpp.opentakrouter.Tests.csproj", "{248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{60D76D5C-4BB5-4AEB-A30B-E3C6139DBC8C}"
11 | ProjectSection(SolutionItems) = preProject
12 | .gitignore = .gitignore
13 | readme.md = readme.md
14 | EndProjectSection
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Debug|x64 = Debug|x64
20 | Debug|x86 = Debug|x86
21 | Release|Any CPU = Release|Any CPU
22 | Release|x64 = Release|x64
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Debug|x64.ActiveCfg = Debug|Any CPU
29 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Debug|x64.Build.0 = Debug|Any CPU
30 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Debug|x86.ActiveCfg = Debug|Any CPU
31 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Debug|x86.Build.0 = Debug|Any CPU
32 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Release|x64.ActiveCfg = Release|Any CPU
35 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Release|x64.Build.0 = Release|Any CPU
36 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Release|x86.ActiveCfg = Release|Any CPU
37 | {73115B5B-9E47-4D60-A3F8-5F92F55D15EA}.Release|x86.Build.0 = Release|Any CPU
38 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Debug|x64.ActiveCfg = Debug|Any CPU
41 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Debug|x64.Build.0 = Debug|Any CPU
42 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Debug|x86.ActiveCfg = Debug|Any CPU
43 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Debug|x86.Build.0 = Debug|Any CPU
44 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Release|x64.ActiveCfg = Release|Any CPU
47 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Release|x64.Build.0 = Release|Any CPU
48 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Release|x86.ActiveCfg = Release|Any CPU
49 | {248DE885-E6F6-4981-A9D3-AF2BC76CB0C0}.Release|x86.Build.0 = Release|Any CPU
50 | EndGlobalSection
51 | GlobalSection(SolutionProperties) = preSolution
52 | HideSolutionNode = FALSE
53 | EndGlobalSection
54 | GlobalSection(ExtensibilityGlobals) = postSolution
55 | SolutionGuid = {5BD31DF3-5404-48BF-A94D-5D8F32045D5A}
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # OpenTakRouter [](https://github.com/darkplusplus/opentakrouter/actions/workflows/ci.yml)
2 |
3 | An opensource router of cursor-on-target messages with support for [ATAK](https://github.com/deptofdefense/AndroidTacticalAssaultKit-CIV).
4 |
5 | ## Features
6 |
7 | - Cross platform emphasizing ease of use.
8 | - Support for both TCP and SSL server modes.
9 | - Datapackages server.
10 | - Live map of current POI.
11 | - Basic federation capabilities (non-ssl for now).
12 | - More to come!
13 |
14 | You can track our current roadmap here: https://github.com/darkplusplus/opentakrouter/projects/1
15 |
16 | ## Quickstart
17 |
18 | 1. Go grab the latest release zip or tarball.
19 | 2. Unarchive to your directory of choice.
20 | 3. Review `opentakrouter.json` to see the default configuration.
21 | 4. Run `opentakrouter`.
22 | 5. Browse to http://localhost:8080 to see the admin pages.
23 | 6. Connect your EUD to your host on port `58087`.
24 |
25 |
26 | ## Want to run this on AWS?
27 |
28 | We have a shortcut to get you online quickly at https://github.com/darkplusplus/opentakrouter-ops.
29 |
--------------------------------------------------------------------------------
/scripts/build-linux.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | VERSION=`git branch --show-current`
5 | HASH=`git rev-parse --short HEAD`
6 |
7 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
8 | DIST_DIR="$SCRIPT_DIR/../dist"
9 |
10 | mkdir -p $DIST_DIR
11 |
12 | # linux
13 | dotnet publish dpp.opentakrouter -c Release -r linux-x64 --self-contained=true -p:PublishSingleFile=true
14 | pushd ./dpp.opentakrouter/bin/Release/net5.0/linux-x64/publish/
15 | tar -czvf $DIST_DIR/opentakrouter-$VERSION-$HASH.tar.gz .
16 | popd
17 |
--------------------------------------------------------------------------------
/scripts/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e
3 |
4 | if [[ -z "$CI" ]]; then
5 | echo "Sorry, but this assumes running in a Github Action" 1>&2
6 | exit 1
7 | fi
8 |
9 | VERSION=$GITHUB_REF_NAME
10 |
11 | SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
12 | DIST_DIR="$SCRIPT_DIR/../dist"
13 |
14 | mkdir -p $DIST_DIR
15 |
16 | dotnet clean
17 |
18 | # win10-x64
19 | ARCH=win10-x64
20 | dotnet publish dpp.opentakrouter -c Release -r $ARCH --self-contained=true -p:PublishSingleFile=true
21 | pushd ./dpp.opentakrouter/bin/Release/net5.0/$ARCH/publish/
22 | zip -r $DIST_DIR/opentakrouter-$VERSION-$ARCH.zip .
23 | popd
24 |
25 | # linux-x64
26 | ARCH=linux-x64
27 | dotnet publish dpp.opentakrouter -c Release -r $ARCH --self-contained=true -p:PublishSingleFile=true
28 | pushd ./dpp.opentakrouter/bin/Release/net5.0/$ARCH/publish/
29 | tar -czvf $DIST_DIR/opentakrouter-$VERSION-$ARCH.tar.gz .
30 | popd
31 |
32 | # linux-arm64
33 | ARCH=linux-arm64
34 | dotnet publish dpp.opentakrouter -c Release -r $ARCH --self-contained=true -p:PublishSingleFile=true
35 | pushd ./dpp.opentakrouter/bin/Release/net5.0/$ARCH/publish/
36 | tar -czvf $DIST_DIR/opentakrouter-$VERSION-$ARCH.tar.gz .
37 | popd
38 |
--------------------------------------------------------------------------------