diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 20e83544..85d34b64 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -54,6 +54,12 @@ jobs:
cmake -G 'Visual Studio 17 2022' -A x64 -DQUIC_TLS=${{ matrix.tls }} -DQUIC_BUILD_SHARED=${{ matrix.shared }} ..
cmake --build . --config Release
cmake --install . --config Release
+ - name: Build Windows Installer
+ if: runner.os == 'Windows'
+ run: |
+ cd build
+ & 'C:/Program Files (x86)/WiX Toolset v3.11/bin/candle.exe' ../src/installer.wxs -o src/Release/quicreach.wixobj
+ & 'C:/Program Files (x86)/WiX Toolset v3.11/bin/light.exe' -b src/Release -o src/Release/quicreach.msi src/Release/quicreach.wixobj
- name: Upload
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8
with:
@@ -63,6 +69,7 @@ jobs:
build/**/*.dll
build/**/quicreach
build/**/quicreach.exe
+ build/**/quicreach.msi
- name: Test (Linux)
if: runner.os == 'Linux'
run: /usr/local/lib/quicreach outlook-evergreen.office.com,www.cloudflare.com,www.google.com --req-all --stats
diff --git a/.gitignore b/.gitignore
index a7678abc..433a83eb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -349,3 +349,6 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
+
+# VSCode folder
+.vscode/
diff --git a/src/installer.wxs b/src/installer.wxs
new file mode 100644
index 00000000..593b9539
--- /dev/null
+++ b/src/installer.wxs
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/quicreach.cpp b/src/quicreach.cpp
index d35b2435..ec9ebdf7 100644
--- a/src/quicreach.cpp
+++ b/src/quicreach.cpp
@@ -16,6 +16,8 @@
#include
#include "domains.hpp"
+#define QUICREACH_VERSION "1.1.0"
+
#ifdef _WIN32
#define QUIC_CALL __cdecl
#else
@@ -97,6 +99,24 @@ void IncStat( _Inout_ _Interlocked_operand_ uint32_t volatile &Addend) {
#endif
}
+void AddHostName(const char* arg) {
+ // Parse hostname(s), treating '*' as all top-level domains.
+ if (!strcmp(arg, "*")) {
+ for (auto Domain : TopDomains) {
+ Config.HostNames.push_back(Domain);
+ }
+ } else {
+ char* HostName = (char*)arg;
+ do {
+ char* End = strchr(HostName, ',');
+ if (End) *End = 0;
+ Config.HostNames.push_back(HostName);
+ if (!End) break;
+ HostName = End + 1;
+ } while (true);
+ }
+}
+
bool ParseConfig(int argc, char **argv) {
if (argc < 2 || !strcmp(argv[1], "-?") || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
printf("usage: quicreach [options...]\n"
@@ -110,29 +130,16 @@ bool ParseConfig(int argc, char **argv) {
" -r, --req-all Require all hostnames to succeed\n"
" -s, --stats Print connection statistics\n"
" -u, --unsecure Allows unsecure connections\n"
+ " -v, --version Prints out the version\n"
);
return false;
}
- // Parse hostname(s), treating '*' as all top-level domains.
- if (!strcmp(argv[1], "*")) {
- for (auto Domain : TopDomains) {
- Config.HostNames.push_back(Domain);
- }
- } else {
- char* HostName = (char*)argv[1];
- do {
- char* End = strchr(HostName, ',');
- if (End) *End = 0;
- Config.HostNames.push_back(HostName);
- if (!End) break;
- HostName = End + 1;
- } while (true);
- }
+ for (int i = 1; i < argc; ++i) {
+ if (argv[i][0] != '-') {
+ AddHostName(argv[i]);
- // Parse options.
- for (int i = 2; i < argc; ++i) {
- if (!strcmp(argv[i], "--alpn") || !strcmp(argv[i], "-a")) {
+ } else if (!strcmp(argv[i], "--alpn") || !strcmp(argv[i], "-a")) {
if (++i >= argc) { printf("Missing ALPN string\n"); return false; }
Config.Alpn = argv[i];
@@ -163,6 +170,9 @@ bool ParseConfig(int argc, char **argv) {
} else if (!strcmp(argv[i], "--unsecure") || !strcmp(argv[i], "-u")) {
Config.CredFlags |= QUIC_CREDENTIAL_FLAG_NO_CERTIFICATE_VALIDATION;
+
+ } else if (!strcmp(argv[i], "--version") || !strcmp(argv[i], "-v")) {
+ printf("quicreach " QUICREACH_VERSION "\n");
}
}
@@ -332,7 +342,7 @@ bool TestReachability() {
int QUIC_CALL main(int argc, char **argv) {
- if (!ParseConfig(argc, argv)) return 1;
+ if (!ParseConfig(argc, argv) || Config.HostNames.empty()) return 1;
MsQuic = new (std::nothrow) MsQuicApi();
if (QUIC_FAILED(MsQuic->GetInitStatus())) {