diff --git a/NetTunnelApp/MainForm.Designer.cs b/NetTunnelApp/MainForm.Designer.cs index 178487f..d7b5ba5 100644 --- a/NetTunnelApp/MainForm.Designer.cs +++ b/NetTunnelApp/MainForm.Designer.cs @@ -28,13 +28,49 @@ /// private void InitializeComponent() { + this.button1 = new System.Windows.Forms.Button(); + this.button2 = new System.Windows.Forms.Button(); + this.lstLogs = new System.Windows.Forms.ListBox(); this.SuspendLayout(); // + // button1 + // + this.button1.Location = new System.Drawing.Point(35, 43); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(98, 27); + this.button1.TabIndex = 0; + this.button1.Text = "button1"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2.Location = new System.Drawing.Point(180, 46); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(96, 24); + this.button2.TabIndex = 1; + this.button2.Text = "button2"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // lstLogs + // + this.lstLogs.FormattingEnabled = true; + this.lstLogs.ItemHeight = 12; + this.lstLogs.Location = new System.Drawing.Point(-1, 204); + this.lstLogs.Name = "lstLogs"; + this.lstLogs.ScrollAlwaysVisible = true; + this.lstLogs.Size = new System.Drawing.Size(800, 244); + this.lstLogs.TabIndex = 2; + // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.lstLogs); + this.Controls.Add(this.button2); + this.Controls.Add(this.button1); this.Name = "MainForm"; this.Text = "NetTunnelApp"; this.ResumeLayout(false); @@ -42,6 +78,10 @@ } #endregion + + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.ListBox lstLogs; } } diff --git a/NetTunnelApp/MainForm.cs b/NetTunnelApp/MainForm.cs index 11beb93..3cc18bf 100644 --- a/NetTunnelApp/MainForm.cs +++ b/NetTunnelApp/MainForm.cs @@ -1,26 +1,67 @@ using System; +using System.Buffers; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox; -namespace NetTunnelApp +namespace NetTunnelApp; + +public partial class MainForm : Form { - public partial class MainForm : Form + public MainForm() { - public MainForm() - { - InitializeComponent(); + InitializeComponent(); + var path = Environment.CurrentDirectory + "\\tunnelsdk_" + + string.Format("{0:yyyyMMdd}", DateTime.Now) + ".log"; + NetTunnelLib.InitTunnelSDKLog(path, LogLevel.LOG_DEBUG); - NetTunnelLib.TunnelSDKInitEnv(); - - string path = System.Environment.CurrentDirectory + "\\tunnelsdk_" + - string.Format("{0:yyyyMMdd_HHmm}", System.DateTime.Now) + ".log"; - NetTunnelLib.InitTunnelSDKLog(path, LogLevel.LOG_DEBUG); - } + NetTunnelLib.TunnelSDKInitEnv(Environment.CurrentDirectory); } -} + + private void button1_Click(object sender, EventArgs e) + { + var buffer = new StringBuilder(256 + 1); + //NetTunnelLib.TunnelSDKInitEnv(); + var v = NetTunnelLib.FindWireguardExe(buffer, 256); + MessageBox.Show(buffer.ToString() + "----" + v.ToString()); + } + + private void button2_Click(object sender, EventArgs e) + { + var buffer = new StringBuilder(64 + 1); + var buffer2 = new StringBuilder(64 + 1); + //var v = NetTunnelLib.RunPipeCmd("cmd.exe /C dir E:\\", buffer, 4096); + //MessageBox.Show(buffer.ToString() + "\nResult: " + v.ToString()); + + var v = NetTunnelLib.GenerateWireguardKeyPairs(buffer, 64, buffer2, 64); + lstLogs.Items.Add(v.ToString() + ": [" + buffer.ToString() + "] / [" + buffer2.ToString() + "]"); + + IntPtr pt = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(NetCard)) * 32); + int size = 0; + + v = NetTunnelLib.GetAllNICInfo(pt, ref size); + + Console.WriteLine("Result {0}, total {1}", v, size); + + for (int i = 0; i < size; i++) + { + IntPtr ptr = new IntPtr(pt.ToInt64() + Marshal.SizeOf(typeof(NetCard)) * i); + NetCard card = (NetCard)Marshal.PtrToStructure(ptr, typeof(NetCard)); + + Console.WriteLine("Name:{0}", card.Name); + Console.WriteLine("Description:{0}", card.Description); + Console.WriteLine("Ip:{0}", card.IpAddr); + Console.WriteLine("NetMask:{0}", card.NetMask); + Console.WriteLine("MacAddr:{0}", card.MacAddr); + } + + Marshal.FreeHGlobal(pt); + } +} \ No newline at end of file diff --git a/NetTunnelApp/NetTunnelApp.csproj b/NetTunnelApp/NetTunnelApp.csproj index 308486f..46eb533 100644 --- a/NetTunnelApp/NetTunnelApp.csproj +++ b/NetTunnelApp/NetTunnelApp.csproj @@ -24,6 +24,7 @@ prompt 4 false + true AnyCPU @@ -33,6 +34,7 @@ TRACE prompt 4 + true LocalIntranet @@ -43,8 +45,14 @@ Properties\app.manifest + + OnOutputUpdated + + + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + @@ -78,6 +86,7 @@ True Resources.resx + SettingsSingleFileGenerator @@ -94,6 +103,11 @@ - copy /y $(SolutionDir)x64\$(ConfigurationName)\*.dll $(TargetDir) + + + + + + \ No newline at end of file diff --git a/NetTunnelApp/NetTunnelLib.cs b/NetTunnelApp/NetTunnelLib.cs index 6728833..aa1341c 100644 --- a/NetTunnelApp/NetTunnelLib.cs +++ b/NetTunnelApp/NetTunnelLib.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using System.Text; namespace NetTunnelApp; @@ -14,10 +15,31 @@ public enum ProtoCryptoType public enum LogLevel { - LOG_DEBUG = 0, - LOG_INFO = 1, - LOG_WARN = 2, - LOG_ERROR = 3 + LOG_TRACE = 0, + LOG_DEBUG, + LOG_INFO, + LOG_WARN, + LOG_ERROR, + LOG_CRITICAL +} + +[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] +public struct NetCard +{ + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string Name; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string Description; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string IpAddr; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string NetMask; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string MacAddr; } public class NetTunnelLib @@ -32,11 +54,30 @@ public class NetTunnelLib internal static extern Int32 Add(int a, int b); [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] - public static extern int TunnelSDKInitEnv(); + public static extern int TunnelSDKInitEnv(String workDir); + + [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern void TunnelSDKUnInit(); [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int SetProtocolEncryptType(ProtoCryptoType type, String pProKey); [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void InitTunnelSDKLog(String pProKey, LogLevel level); + + [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int FindWireguardExe(StringBuilder lpString, int maxSize); + + [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int SetWireguardPath(String path); + + [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int GenerateWireguardKeyPairs(StringBuilder wgPubKey, int maxPubKey, StringBuilder wgPrivKey, + int MaxPrivKey); + + [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int GetAllNICInfo(IntPtr netCard, ref int size); + + //[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)] + //public static extern int RunPipeCmd(String pszCmd, StringBuilder pszResultBuffer, int dwResultBufferSize); } \ No newline at end of file diff --git a/NetTunnelApp/packages.config b/NetTunnelApp/packages.config new file mode 100644 index 0000000..ffb547c --- /dev/null +++ b/NetTunnelApp/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj b/NetTunnelSDK/NetTunnelSDK.vcxproj index ba88b08..bfffee4 100644 --- a/NetTunnelSDK/NetTunnelSDK.vcxproj +++ b/NetTunnelSDK/NetTunnelSDK.vcxproj @@ -120,6 +120,12 @@ true false + + copy /y $(TargetDir)*.dll $(SolutionDir)\NetTunnelApp\bin\$(ConfigurationName)\ + + + + @@ -142,8 +148,7 @@ - - + @@ -151,9 +156,8 @@ - - NotUsing - + + Create Create @@ -167,7 +171,7 @@ NotUsing - NotUsing + Use diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters index c7c2332..f2bd655 100644 --- a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters +++ b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters @@ -30,10 +30,7 @@ 头文件 - - 头文件 - - + 头文件 @@ -50,10 +47,13 @@ 源文件 - + 源文件 - + + 源文件 + + 源文件 diff --git a/NetTunnelSDK/dllmain.cpp b/NetTunnelSDK/dllmain.cpp index 606b0fe..3c50790 100644 --- a/NetTunnelSDK/dllmain.cpp +++ b/NetTunnelSDK/dllmain.cpp @@ -1,11 +1,11 @@ // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "pch.h" -#include "logs/fmtlog.h" +#include "tunnel.h" -BOOL APIENTRY DllMain( HMODULE hModule, - DWORD ul_reason_for_call, - LPVOID lpReserved - ) +BOOL APIENTRY DllMain(HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved +) { switch (ul_reason_for_call) { @@ -13,9 +13,8 @@ BOOL APIENTRY DllMain( HMODULE hModule, case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: - fmtlog::poll(); + TunnelSDKUnInit(); break; } return TRUE; } - diff --git a/NetTunnelSDK/globalcfg.h b/NetTunnelSDK/globalcfg.h new file mode 100644 index 0000000..c30a4bb --- /dev/null +++ b/NetTunnelSDK/globalcfg.h @@ -0,0 +1,21 @@ +#pragma once +#include + +typedef struct +{ + TCHAR wireguardPath[MAX_PATH]; + BOOL wireguardExists; + TCHAR wgPath[MAX_PATH]; + BOOL wgExists; +} WIREGUARD_CFG, *PWIREGUARD_CFG; + +typedef struct +{ + TCHAR workDirectory[MAX_PATH]; + PROTO_CRYPTO_TYPE proCryptoType; + TCHAR proKeyBuf[CRYPTO_MAX][256]; + spdlog::level::level_enum logLevel; + WIREGUARD_CFG wireguardCfg; +} SDK_CONFIG, *PSDK_CONFIG; + +PSDK_CONFIG GetGlobalCfgInfo(); diff --git a/NetTunnelSDK/logs/fmtlog-inl.h b/NetTunnelSDK/logs/fmtlog-inl.h deleted file mode 100644 index ad8b1bf..0000000 --- a/NetTunnelSDK/logs/fmtlog-inl.h +++ /dev/null @@ -1,636 +0,0 @@ -/* -MIT License - -Copyright (c) 2021 Meng Rao - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -#pragma warning( disable : 4996) -#include "fmtlog.h" -#include -#include -#include -#include - -#ifdef _WIN32 -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#include -#else -#include -#include -#endif - -namespace { -void fmtlogEmptyFun(void*) { -} -} // namespace - -template -class fmtlogDetailT -{ -public: - // https://github.com/MengRao/str - template - class Str - { - public: - static const int Size = SIZE; - char s[SIZE]; - - Str() {} - Str(const char* p) { *this = *(const Str*)p; } - - char& operator[](int i) { return s[i]; } - char operator[](int i) const { return s[i]; } - - template - void fromi(T num) { - if constexpr (Size & 1) { - s[Size - 1] = '0' + (num % 10); - num /= 10; - } - switch (Size & -2) { - case 18: *(uint16_t*)(s + 16) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - case 16: *(uint16_t*)(s + 14) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - case 14: *(uint16_t*)(s + 12) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - case 12: *(uint16_t*)(s + 10) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - case 10: *(uint16_t*)(s + 8) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - case 8: *(uint16_t*)(s + 6) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - case 6: *(uint16_t*)(s + 4) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - case 4: *(uint16_t*)(s + 2) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - case 2: *(uint16_t*)(s + 0) = *(uint16_t*)(digit_pairs + ((num % 100) << 1)); num /= 100; - } - } - - static constexpr const char* digit_pairs = "00010203040506070809" - "10111213141516171819" - "20212223242526272829" - "30313233343536373839" - "40414243444546474849" - "50515253545556575859" - "60616263646566676869" - "70717273747576777879" - "80818283848586878889" - "90919293949596979899"; - }; - - fmtlogDetailT() - : flushDelay(3000000000) { - args.reserve(4096); - args.resize(parttenArgSize); - - fmtlogWrapper<>::impl.init(); - resetDate(); - fmtlog::setLogFile(stdout); - setHeaderPattern("{HMSf} {s:<16} {l}[{t:<6}] "); - logInfos.reserve(32); - bgLogInfos.reserve(128); - bgLogInfos.emplace_back(nullptr, nullptr, fmtlog::DBG, fmt::string_view()); - bgLogInfos.emplace_back(nullptr, nullptr, fmtlog::INF, fmt::string_view()); - bgLogInfos.emplace_back(nullptr, nullptr, fmtlog::WRN, fmt::string_view()); - bgLogInfos.emplace_back(nullptr, nullptr, fmtlog::ERR, fmt::string_view()); - threadBuffers.reserve(8); - bgThreadBuffers.reserve(8); - memset(membuf.data(), 0, membuf.capacity()); - } - - ~fmtlogDetailT() { - stopPollingThread(); - poll(true); - closeLogFile(); - } - - void setHeaderPattern(const char* pattern) { - if (shouldDeallocateHeader) delete[] headerPattern.data(); - using namespace fmt::literals; - for (int i = 0; i < parttenArgSize; i++) { - reorderIdx[i] = parttenArgSize - 1; - } - headerPattern = fmtlog::unNameFormat( - pattern, reorderIdx, "a"_a = "", "b"_a = "", "C"_a = "", "Y"_a = "", "m"_a = "", "d"_a = "", - "t"_a = "thread name", "F"_a = "", "f"_a = "", "e"_a = "", "S"_a = "", "M"_a = "", "H"_a = "", - "l"_a = fmtlog::LogLevel(), "s"_a = "fmtlog.cc:123", "g"_a = "/home/raomeng/fmtlog/fmtlog.cc:123", "Ymd"_a = "", - "HMS"_a = "", "HMSe"_a = "", "HMSf"_a = "", "HMSF"_a = "", "YmdHMS"_a = "", "YmdHMSe"_a = "", "YmdHMSf"_a = "", - "YmdHMSF"_a = ""); - shouldDeallocateHeader = headerPattern.data() != pattern; - - setArg<0>(fmt::string_view(weekdayName.s, 3)); - setArg<1>(fmt::string_view(monthName.s, 3)); - setArg<2>(fmt::string_view(&year[2], 2)); - setArg<3>(fmt::string_view(year.s, 4)); - setArg<4>(fmt::string_view(month.s, 2)); - setArg<5>(fmt::string_view(day.s, 2)); - setArg<6>(fmt::string_view()); - setArg<7>(fmt::string_view(nanosecond.s, 9)); - setArg<8>(fmt::string_view(nanosecond.s, 6)); - setArg<9>(fmt::string_view(nanosecond.s, 3)); - setArg<10>(fmt::string_view(second.s, 2)); - setArg<11>(fmt::string_view(minute.s, 2)); - setArg<12>(fmt::string_view(hour.s, 2)); - setArg<13>(fmt::string_view(logLevel.s, 3)); - setArg<14>(fmt::string_view()); - setArg<15>(fmt::string_view()); - setArg<16>(fmt::string_view(year.s, 10)); // Ymd - setArg<17>(fmt::string_view(hour.s, 8)); // HMS - setArg<18>(fmt::string_view(hour.s, 12)); // HMSe - setArg<19>(fmt::string_view(hour.s, 15)); // HMSf - setArg<20>(fmt::string_view(hour.s, 18)); // HMSF - setArg<21>(fmt::string_view(year.s, 19)); // YmdHMS - setArg<22>(fmt::string_view(year.s, 23)); // YmdHMSe - setArg<23>(fmt::string_view(year.s, 26)); // YmdHMSf - setArg<24>(fmt::string_view(year.s, 29)); // YmdHMSF - } - - class ThreadBufferDestroyer - { - public: - explicit ThreadBufferDestroyer() {} - - void threadBufferCreated() {} - - ~ThreadBufferDestroyer() { - if (fmtlog::threadBuffer != nullptr) { - fmtlog::threadBuffer->shouldDeallocate = true; - fmtlog::threadBuffer = nullptr; - } - } - }; - - struct StaticLogInfo - { - // Constructor - constexpr StaticLogInfo(fmtlog::FormatToFn fn, const char* loc, fmtlog::LogLevel level, fmt::string_view fmtString) - : formatToFn(fn) - , formatString(fmtString) - , location(loc) - , logLevel(level) - , argIdx(-1) {} - - void processLocation() { - size_t size = strlen(location); - const char* p = location + size; - if (size > 255) { - location = p - 255; - } - endPos = p - location; - const char* base = location; - while (p > location) { - char c = *--p; - if (c == '/' || c == '\\') { - base = p + 1; - break; - } - } - basePos = base - location; - } - - inline fmt::string_view getBase() { return fmt::string_view(location + basePos, endPos - basePos); } - - inline fmt::string_view getLocation() { return fmt::string_view(location, endPos); } - - fmtlog::FormatToFn formatToFn; - fmt::string_view formatString; - const char* location; - uint8_t basePos; - uint8_t endPos; - fmtlog::LogLevel logLevel; - int argIdx; - }; - - static thread_local ThreadBufferDestroyer sbc; - int64_t midnightNs; - fmt::string_view headerPattern; - bool shouldDeallocateHeader = false; - FILE* outputFp = nullptr; - bool manageFp = false; - size_t fpos = 0; // file position of membuf, used only when manageFp == true - int64_t flushDelay; - int64_t nextFlushTime = (std::numeric_limits::max)(); - uint32_t flushBufSize = 8 * 1024; - fmtlog::LogLevel flushLogLevel = fmtlog::OFF; - std::mutex bufferMutex; - std::vector threadBuffers; - struct HeapNode - { - HeapNode(fmtlog::ThreadBuffer* buffer) - : tb(buffer) {} - - fmtlog::ThreadBuffer* tb; - const fmtlog::SPSCVarQueueOPT::MsgHeader* header = nullptr; - }; - std::vector bgThreadBuffers; - std::mutex logInfoMutex; - std::vector logInfos; - std::vector bgLogInfos; - - fmtlog::LogCBFn logCB = nullptr; - fmtlog::LogLevel minCBLogLevel; - fmtlog::LogQFullCBFn logQFullCB = fmtlogEmptyFun; - void* logQFullCBArg = nullptr; - - fmtlog::MemoryBuffer membuf; - - const static int parttenArgSize = 25; - uint32_t reorderIdx[parttenArgSize]; - Str<3> weekdayName; - Str<3> monthName; - Str<4> year; - char dash1 = '-'; - Str<2> month; - char dash2 = '-'; - Str<2> day; - char space = ' '; - Str<2> hour; - char colon1 = ':'; - Str<2> minute; - char colon2 = ':'; - Str<2> second; - char dot1 = '.'; - Str<9> nanosecond; - Str<3> logLevel; - std::vector> args; - - volatile bool threadRunning = false; - std::thread thr; - - void resetDate() { - time_t rawtime = fmtlogWrapper<>::impl.tscns.rdns() / 1000000000; - struct tm* timeinfo = localtime(&rawtime); - timeinfo->tm_sec = timeinfo->tm_min = timeinfo->tm_hour = 0; - midnightNs = mktime(timeinfo) * 1000000000; - year.fromi(1900 + timeinfo->tm_year); - month.fromi(1 + timeinfo->tm_mon); - day.fromi(timeinfo->tm_mday); - const char* weekdays[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; - weekdayName = weekdays[timeinfo->tm_wday]; - const char* monthNames[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - monthName = monthNames[timeinfo->tm_mon]; - } - - void preallocate() { - if (fmtlog::threadBuffer) return; - fmtlog::threadBuffer = new fmtlog::ThreadBuffer(); -#ifdef _WIN32 - uint32_t tid = static_cast(::GetCurrentThreadId()); -#else - uint32_t tid = static_cast(::syscall(SYS_gettid)); -#endif - fmtlog::threadBuffer->nameSize = - fmt::format_to_n(fmtlog::threadBuffer->name, sizeof(fmtlog::threadBuffer->name), "{}", tid).size; - sbc.threadBufferCreated(); - - std::unique_lock guard(bufferMutex); - threadBuffers.push_back(fmtlog::threadBuffer); - } - - template - inline void setArg(const T& arg) { - args[reorderIdx[I]] = fmt::detail::make_arg(arg); - } - - template - inline void setArgVal(const T& arg) { - fmt::detail::value& value_ = *(fmt::detail::value*)&args[reorderIdx[I]]; - value_ = fmt::detail::arg_mapper().map(arg); - } - - void flushLogFile() { - if (outputFp) { - fwrite(membuf.data(), 1, membuf.size(), outputFp); - if (!manageFp) fflush(outputFp); - else - fpos += membuf.size(); - } - membuf.clear(); - nextFlushTime = (std::numeric_limits::max)(); - } - - void closeLogFile() { - if (membuf.size()) flushLogFile(); - if (manageFp) fclose(outputFp); - outputFp = nullptr; - manageFp = false; - } - - void startPollingThread(int64_t pollInterval) { - stopPollingThread(); - threadRunning = true; - thr = std::thread([pollInterval, this]() { - while (threadRunning) { - int64_t before = fmtlogWrapper<>::impl.tscns.rdns(); - poll(false); - int64_t delay = fmtlogWrapper<>::impl.tscns.rdns() - before; - if (delay < pollInterval) { - std::this_thread::sleep_for(std::chrono::nanoseconds(pollInterval - delay)); - } - } - poll(true); - }); - } - - void stopPollingThread() { - if (!threadRunning) return; - threadRunning = false; - if (thr.joinable()) thr.join(); - } - - void handleLog(fmt::string_view threadName, const fmtlog::SPSCVarQueueOPT::MsgHeader* header) { - setArgVal<6>(threadName); - StaticLogInfo& info = bgLogInfos[header->logId]; - const char* data = (const char*)(header + 1); - const char* end = (const char*)header + header->size; - int64_t tsc = *(int64_t*)data; - data += 8; - if (!info.formatToFn) { // log once - info.location = *(const char**)data; - data += 8; - info.processLocation(); - } - int64_t ts = fmtlogWrapper<>::impl.tscns.tsc2ns(tsc); - // the date could go back when polling different threads - uint64_t t = (ts > midnightNs) ? (ts - midnightNs) : 0; - nanosecond.fromi(t % 1000000000); - t /= 1000000000; - second.fromi(t % 60); - t /= 60; - minute.fromi(t % 60); - t /= 60; - uint32_t h = t; // hour - if (h > 23) { - h %= 24; - resetDate(); - } - hour.fromi(h); - setArgVal<14>(info.getBase()); - setArgVal<15>(info.getLocation()); - logLevel = (const char*)"DBG INF WRN ERR OFF" + (info.logLevel << 2); - - size_t headerPos = membuf.size(); - fmtlog::vformat_to(membuf, headerPattern, fmt::basic_format_args(args.data(), parttenArgSize)); - size_t bodyPos = membuf.size(); - - if (info.formatToFn) { - info.formatToFn(info.formatString, data, membuf, info.argIdx, args); - } - else { // log once - membuf.append(fmt::string_view(data, end - data)); - } - - if (logCB && info.logLevel >= minCBLogLevel) { - logCB(ts, info.logLevel, info.getLocation(), info.basePos, threadName, - fmt::string_view(membuf.data() + headerPos, membuf.size() - headerPos), bodyPos - headerPos, - fpos + headerPos); - } - membuf.push_back('\n'); - if (membuf.size() >= flushBufSize || info.logLevel >= flushLogLevel) { - flushLogFile(); - } - } - - void adjustHeap(size_t i) { - while (true) { - size_t min_i = i; - for (size_t ch = i * 2 + 1, end = std::min(ch + 2, bgThreadBuffers.size()); ch < end; ch++) { - auto h_ch = bgThreadBuffers[ch].header; - auto h_min = bgThreadBuffers[min_i].header; - if (h_ch && (!h_min || *(int64_t*)(h_ch + 1) < *(int64_t*)(h_min + 1))) min_i = ch; - } - if (min_i == i) break; - std::swap(bgThreadBuffers[i], bgThreadBuffers[min_i]); - i = min_i; - } - } - - void poll(bool forceFlush) { - fmtlogWrapper<>::impl.tscns.calibrate(); - int64_t tsc = fmtlogWrapper<>::impl.tscns.rdtsc(); - if (logInfos.size()) { - std::unique_lock lock(logInfoMutex); - for (auto& info : logInfos) { - info.processLocation(); - } - bgLogInfos.insert(bgLogInfos.end(), logInfos.begin(), logInfos.end()); - logInfos.clear(); - } - if (threadBuffers.size()) { - std::unique_lock lock(bufferMutex); - for (auto tb : threadBuffers) { - bgThreadBuffers.emplace_back(tb); - } - threadBuffers.clear(); - } - - for (size_t i = 0; i < bgThreadBuffers.size(); i++) { - auto& node = bgThreadBuffers[i]; - if (node.header) continue; - node.header = node.tb->varq.front(); - if (!node.header && node.tb->shouldDeallocate) { - delete node.tb; - node = bgThreadBuffers.back(); - bgThreadBuffers.pop_back(); - i--; - } - } - - if (bgThreadBuffers.empty()) return; - - // build heap - for (int i = bgThreadBuffers.size() / 2; i >= 0; i--) { - adjustHeap(i); - } - - while (true) { - auto h = bgThreadBuffers[0].header; - if (!h || h->logId >= bgLogInfos.size() || *(int64_t*)(h + 1) >= tsc) break; - auto tb = bgThreadBuffers[0].tb; - handleLog(fmt::string_view(tb->name, tb->nameSize), h); - tb->varq.pop(); - bgThreadBuffers[0].header = tb->varq.front(); - adjustHeap(0); - } - - if (membuf.size() == 0) return; - if (!manageFp || forceFlush) { - flushLogFile(); - return; - } - int64_t now = fmtlogWrapper<>::impl.tscns.tsc2ns(tsc); - if (now > nextFlushTime) { - flushLogFile(); - } - else if (nextFlushTime == (std::numeric_limits::max)()) { - nextFlushTime = now + flushDelay; - } - } -}; - -template -thread_local typename fmtlogDetailT<_>::ThreadBufferDestroyer fmtlogDetailT<_>::sbc; - -template -struct fmtlogDetailWrapper -{ static fmtlogDetailT<> impl; }; - -template -fmtlogDetailT<> fmtlogDetailWrapper<_>::impl; - -template -void fmtlogT<_>::registerLogInfo(uint32_t& logId, FormatToFn fn, const char* location, - LogLevel level, fmt::string_view fmtString) noexcept { - auto& d = fmtlogDetailWrapper<>::impl; - std::lock_guard lock(d.logInfoMutex); - if (logId) return; - logId = d.logInfos.size() + d.bgLogInfos.size(); - d.logInfos.emplace_back(fn, location, level, fmtString); -} - -template -void fmtlogT<_>::vformat_to(fmtlog::MemoryBuffer& out, fmt::string_view fmt, - fmt::format_args args) { - fmt::detail::vformat_to(out, fmt, args); -} - -template -size_t fmtlogT<_>::formatted_size(fmt::string_view fmt, fmt::format_args args) { - auto buf = fmt::detail::counting_buffer<>(); - fmt::detail::vformat_to(buf, fmt, args); - return buf.count(); -} - -template -void fmtlogT<_>::vformat_to(char* out, fmt::string_view fmt, fmt::format_args args) { - fmt::vformat_to(out, fmt, args); -} - -template -typename fmtlogT<_>::SPSCVarQueueOPT::MsgHeader* fmtlogT<_>::allocMsg(uint32_t size, - bool q_full_cb) noexcept { - auto& d = fmtlogDetailWrapper<>::impl; - if (threadBuffer == nullptr) preallocate(); - auto ret = threadBuffer->varq.alloc(size); - if ((ret == nullptr) & q_full_cb) d.logQFullCB(d.logQFullCBArg); - return ret; -} - -template -typename fmtlogT<_>::SPSCVarQueueOPT::MsgHeader* -fmtlogT<_>::SPSCVarQueueOPT::allocMsg(uint32_t size) noexcept { - return alloc(size); -} - -template -void fmtlogT<_>::preallocate() noexcept { - fmtlogDetailWrapper<>::impl.preallocate(); -} - -template -void fmtlogT<_>::setLogFile(const char* filename, bool truncate) { - auto& d = fmtlogDetailWrapper<>::impl; - FILE* newFp = fopen(filename, truncate ? "w" : "a"); - if (!newFp) { - std::string err = fmt::format("Unable to open file: {}: {}", filename, strerror(errno)); - fmt::detail::throw_format_error(err.c_str()); - } - setbuf(newFp, nullptr); - d.fpos = ftell(newFp); - - closeLogFile(); - d.outputFp = newFp; - d.manageFp = true; -} - -template -void fmtlogT<_>::setLogFile(FILE* fp, bool manageFp) { - auto& d = fmtlogDetailWrapper<>::impl; - closeLogFile(); - if (manageFp) { - setbuf(fp, nullptr); - d.fpos = ftell(fp); - } - else - d.fpos = 0; - d.outputFp = fp; - d.manageFp = manageFp; -} - -template -void fmtlogT<_>::setFlushDelay(int64_t ns) noexcept { - fmtlogDetailWrapper<>::impl.flushDelay = ns; -} - -template -void fmtlogT<_>::flushOn(LogLevel flushLogLevel) noexcept { - fmtlogDetailWrapper<>::impl.flushLogLevel = flushLogLevel; -} - -template -void fmtlogT<_>::setFlushBufSize(uint32_t bytes) noexcept { - fmtlogDetailWrapper<>::impl.flushBufSize = bytes; -} - -template -void fmtlogT<_>::closeLogFile() noexcept { - fmtlogDetailWrapper<>::impl.closeLogFile(); -} - -template -void fmtlogT<_>::poll(bool forceFlush) { - fmtlogDetailWrapper<>::impl.poll(forceFlush); -} - -template -void fmtlogT<_>::setThreadName(const char* name) noexcept { - preallocate(); - threadBuffer->nameSize = fmt::format_to_n(threadBuffer->name, sizeof(fmtlog::threadBuffer->name), "{}", name).size; -} - -template -void fmtlogT<_>::setLogCB(LogCBFn cb, LogLevel minCBLogLevel_) noexcept { - auto& d = fmtlogDetailWrapper<>::impl; - d.logCB = cb; - d.minCBLogLevel = minCBLogLevel_; -} - -template -void fmtlogT<_>::setLogQFullCB(LogQFullCBFn cb, void* userData) noexcept { - auto& d = fmtlogDetailWrapper<>::impl; - d.logQFullCB = cb; - d.logQFullCBArg = userData; -} - -template -void fmtlogT<_>::setHeaderPattern(const char* pattern) { - fmtlogDetailWrapper<>::impl.setHeaderPattern(pattern); -} - -template -void fmtlogT<_>::startPollingThread(int64_t pollInterval) noexcept { - fmtlogDetailWrapper<>::impl.startPollingThread(pollInterval); -} - -template -void fmtlogT<_>::stopPollingThread() noexcept { - fmtlogDetailWrapper<>::impl.stopPollingThread(); -} - -template class fmtlogT<0>; - diff --git a/NetTunnelSDK/logs/fmtlog.cc b/NetTunnelSDK/logs/fmtlog.cc deleted file mode 100644 index da6c2ce..0000000 --- a/NetTunnelSDK/logs/fmtlog.cc +++ /dev/null @@ -1 +0,0 @@ -#include "fmtlog-inl.h" diff --git a/NetTunnelSDK/logs/fmtlog.h b/NetTunnelSDK/logs/fmtlog.h deleted file mode 100644 index a572086..0000000 --- a/NetTunnelSDK/logs/fmtlog.h +++ /dev/null @@ -1,826 +0,0 @@ -/* -MIT License - -Copyright (c) 2021 Meng Rao - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -#pragma once -//#define FMT_HEADER_ONLY -#include "fmt/format.h" -#include -#include -#include -#include -#include -#include - -#ifdef _MSC_VER -#include -#endif - -#ifdef _WIN32 -#define FAST_THREAD_LOCAL thread_local -#else -#define FAST_THREAD_LOCAL __thread -#endif - -// define FMTLOG_BLOCK=1 if log statment should be blocked when queue is full, instead of discarding the msg -#ifndef FMTLOG_BLOCK -#define FMTLOG_BLOCK 0 -#endif - -#define FMTLOG_LEVEL_DBG 0 -#define FMTLOG_LEVEL_INF 1 -#define FMTLOG_LEVEL_WRN 2 -#define FMTLOG_LEVEL_ERR 3 -#define FMTLOG_LEVEL_OFF 4 - -// define FMTLOG_ACTIVE_LEVEL to turn off low log level in compile time -#ifndef FMTLOG_ACTIVE_LEVEL -#define FMTLOG_ACTIVE_LEVEL FMTLOG_LEVEL_DBG -#endif - -#ifndef FMTLOG_QUEUE_SIZE -#define FMTLOG_QUEUE_SIZE (1 << 20) -#endif - -namespace fmtlogdetail { -template -struct UnrefPtr : std::false_type -{ using type = Arg; }; - -template<> -struct UnrefPtr : std::false_type -{ using type = char*; }; - -template<> -struct UnrefPtr : std::false_type -{ using type = void*; }; - -template -struct UnrefPtr> : std::true_type -{ using type = Arg; }; - -template -struct UnrefPtr> : std::true_type -{ using type = Arg; }; - -template -struct UnrefPtr : std::true_type -{ using type = Arg; }; - -}; // namespace fmtlogdetail - -template -class fmtlogT -{ -public: - enum LogLevel : uint8_t - { - DBG = 0, - INF, - WRN, - ERR, - OFF - }; - - // Preallocate thread queue for current thread - static void preallocate() noexcept; - - // Set the file for logging - static void setLogFile(const char* filename, bool truncate = false); - - // Set an existing FILE* for logging, if manageFp is false fmtlog will not buffer log internally - // and will not close the FILE* - static void setLogFile(FILE* fp, bool manageFp = false); - - // Collect log msgs from all threads and write to log file - // If forceFlush = true, internal file buffer is flushed - // User need to call poll() repeatedly if startPollingThread is not used - static void poll(bool forceFlush = false); - - // Set flush delay in nanosecond - // If there's msg older than ns in the buffer, flush will be triggered - static void setFlushDelay(int64_t ns) noexcept; - - // If current msg has level >= flushLogLevel, flush will be triggered - static void flushOn(LogLevel flushLogLevel) noexcept; - - // If file buffer has more than specified bytes, flush will be triggered - static void setFlushBufSize(uint32_t bytes) noexcept; - - // callback signature user can register - // ns: nanosecond timestamp - // level: logLevel - // location: full file path with line num, e.g: /home/raomeng/fmtlog/fmtlog.h:45 - // basePos: file base index in the location - // threadName: thread id or the name user set with setThreadName - // msg: full log msg with header - // bodyPos: log body index in the msg - // logFilePos: log file position of this msg - typedef void (*LogCBFn)(int64_t ns, LogLevel level, fmt::string_view location, size_t basePos, - fmt::string_view threadName, fmt::string_view msg, size_t bodyPos, - size_t logFilePos); - - // Set a callback function for all log msgs with a mininum log level - static void setLogCB(LogCBFn cb, LogLevel minCBLogLevel) noexcept; - - typedef void (*LogQFullCBFn)(void* userData); - static void setLogQFullCB(LogQFullCBFn cb, void* userData) noexcept; - - // Close the log file and subsequent msgs will not be written into the file, - // but callback function can still be used - static void closeLogFile() noexcept; - - // Set log header pattern with fmt named arguments - static void setHeaderPattern(const char* pattern); - - // Set a name for current thread, it'll be shown in {t} part in header pattern - static void setThreadName(const char* name) noexcept; - - // Set current log level, lower level log msgs will be discarded - static inline void setLogLevel(LogLevel logLevel) noexcept; - - // Get current log level - static inline LogLevel getLogLevel() noexcept; - - // return true if passed log level is not lower than current log level - static inline bool checkLogLevel(LogLevel logLevel) noexcept; - - // Run a polling thread in the background with a polling interval in ns - // Note that user must not call poll() himself when the thread is running - static void startPollingThread(int64_t pollInterval = 1000000000) noexcept; - - // Stop the polling thread - static void stopPollingThread() noexcept; - - // https://github.com/MengRao/SPSC_Queue - class SPSCVarQueueOPT - { - public: - struct MsgHeader - { - inline void push(uint32_t sz) { *(volatile uint32_t*)&size = sz + sizeof(MsgHeader); } - - uint32_t size; - uint32_t logId; - }; - static constexpr uint32_t BLK_CNT = FMTLOG_QUEUE_SIZE / sizeof(MsgHeader); - - MsgHeader* allocMsg(uint32_t size) noexcept; - - MsgHeader* alloc(uint32_t size) { - size += sizeof(MsgHeader); - uint32_t blk_sz = (size + sizeof(MsgHeader) - 1) / sizeof(MsgHeader); - if (blk_sz >= free_write_cnt) { - uint32_t read_idx_cache = *(volatile uint32_t*)&read_idx; - if (read_idx_cache <= write_idx) { - free_write_cnt = BLK_CNT - write_idx; - if (blk_sz >= free_write_cnt && read_idx_cache != 0) { // wrap around - blk[0].size = 0; - blk[write_idx].size = 1; - write_idx = 0; - free_write_cnt = read_idx_cache; - } - } - else { - free_write_cnt = read_idx_cache - write_idx; - } - if (free_write_cnt <= blk_sz) { - return nullptr; - } - } - MsgHeader* ret = &blk[write_idx]; - write_idx += blk_sz; - free_write_cnt -= blk_sz; - blk[write_idx].size = 0; - return ret; - } - - inline const MsgHeader* front() { - uint32_t size = blk[read_idx].size; - if (size == 1) { // wrap around - read_idx = 0; - size = blk[0].size; - } - if (size == 0) return nullptr; - return &blk[read_idx]; - } - - inline void pop() { - uint32_t blk_sz = (blk[read_idx].size + sizeof(MsgHeader) - 1) / sizeof(MsgHeader); - *(volatile uint32_t*)&read_idx = read_idx + blk_sz; - } - - private: - alignas(64) MsgHeader blk[BLK_CNT] = {}; - uint32_t write_idx = 0; - uint32_t free_write_cnt = BLK_CNT; - - alignas(128) uint32_t read_idx = 0; - }; - - struct ThreadBuffer - { - SPSCVarQueueOPT varq; - bool shouldDeallocate = false; - char name[32]; - size_t nameSize; - }; - - // https://github.com/MengRao/tscns - class TSCNS - { - public: - static const int64_t NsPerSec = 1000000000; - - void init(int64_t init_calibrate_ns = 20000000, int64_t calibrate_interval_ns = 3 * NsPerSec) { - calibate_interval_ns_ = calibrate_interval_ns; - int64_t base_tsc, base_ns; - syncTime(base_tsc, base_ns); - int64_t expire_ns = base_ns + init_calibrate_ns; - while (rdsysns() < expire_ns) std::this_thread::yield(); - int64_t delayed_tsc, delayed_ns; - syncTime(delayed_tsc, delayed_ns); - double init_ns_per_tsc = (double)(delayed_ns - base_ns) / (delayed_tsc - base_tsc); - saveParam(base_tsc, base_ns, base_ns, init_ns_per_tsc); - } - - void calibrate() { - if (rdtsc() < next_calibrate_tsc_) return; - int64_t tsc, ns; - syncTime(tsc, ns); - int64_t calulated_ns = tsc2ns(tsc); - int64_t ns_err = calulated_ns - ns; - int64_t expected_err_at_next_calibration = - ns_err + (ns_err - base_ns_err_) * calibate_interval_ns_ / (ns - base_ns_ + base_ns_err_); - double new_ns_per_tsc = - ns_per_tsc_ * (1.0 - (double)expected_err_at_next_calibration / calibate_interval_ns_); - saveParam(tsc, calulated_ns, ns, new_ns_per_tsc); - } - - static inline int64_t rdtsc() { -#ifdef _MSC_VER - return __rdtsc(); -#elif defined(__i386__) || defined(__x86_64__) || defined(__amd64__) - return __builtin_ia32_rdtsc(); -#else - return rdsysns(); -#endif - } - - inline int64_t tsc2ns(int64_t tsc) const { - while (true) { - uint32_t before_seq = param_seq_.load(std::memory_order_acquire) & ~1; - std::atomic_signal_fence(std::memory_order_acq_rel); - int64_t ns = base_ns_ + (int64_t)((tsc - base_tsc_) * ns_per_tsc_); - std::atomic_signal_fence(std::memory_order_acq_rel); - uint32_t after_seq = param_seq_.load(std::memory_order_acquire); - if (before_seq == after_seq) return ns; - } - } - - inline int64_t rdns() const { return tsc2ns(rdtsc()); } - - static inline int64_t rdsysns() { - using namespace std::chrono; - return duration_cast(system_clock::now().time_since_epoch()).count(); - } - - double getTscGhz() const { return 1.0 / ns_per_tsc_; } - - // Linux kernel sync time by finding the first trial with tsc diff < 50000 - // We try several times and return the one with the mininum tsc diff. - // Note that MSVC has a 100ns resolution clock, so we need to combine those ns with the same - // value, and drop the first and the last value as they may not scan a full 100ns range - static void syncTime(int64_t& tsc_out, int64_t& ns_out) { -#ifdef _MSC_VER - const int N = 15; -#else - const int N = 3; -#endif - int64_t tsc[N + 1]; - int64_t ns[N + 1]; - - tsc[0] = rdtsc(); - for (int i = 1; i <= N; i++) { - ns[i] = rdsysns(); - tsc[i] = rdtsc(); - } - -#ifdef _MSC_VER - int j = 1; - for (int i = 2; i <= N; i++) { - if (ns[i] == ns[i - 1]) continue; - tsc[j - 1] = tsc[i - 1]; - ns[j++] = ns[i]; - } - j--; -#else - int j = N + 1; -#endif - - int best = 1; - for (int i = 2; i < j; i++) { - if (tsc[i] - tsc[i - 1] < tsc[best] - tsc[best - 1]) best = i; - } - tsc_out = (tsc[best] + tsc[best - 1]) >> 1; - ns_out = ns[best]; - } - - void saveParam(int64_t base_tsc, int64_t base_ns, int64_t sys_ns, double new_ns_per_tsc) { - base_ns_err_ = base_ns - sys_ns; - next_calibrate_tsc_ = base_tsc + (int64_t)((calibate_interval_ns_ - 1000) / new_ns_per_tsc); - uint32_t seq = param_seq_.load(std::memory_order_relaxed); - param_seq_.store(++seq, std::memory_order_release); - std::atomic_signal_fence(std::memory_order_acq_rel); - base_tsc_ = base_tsc; - base_ns_ = base_ns; - ns_per_tsc_ = new_ns_per_tsc; - std::atomic_signal_fence(std::memory_order_acq_rel); - param_seq_.store(++seq, std::memory_order_release); - } - - alignas(64) std::atomic param_seq_ = 0; - double ns_per_tsc_; - int64_t base_tsc_; - int64_t base_ns_; - int64_t calibate_interval_ns_; - int64_t base_ns_err_; - int64_t next_calibrate_tsc_; - }; - - void init() { - tscns.init(); - currentLogLevel = INF; - } - - using Context = fmt::format_context; - using MemoryBuffer = fmt::basic_memory_buffer; - typedef const char* (*FormatToFn)(fmt::string_view format, const char* data, MemoryBuffer& out, - int& argIdx, std::vector>& args); - - static void registerLogInfo(uint32_t& logId, FormatToFn fn, const char* location, LogLevel level, - fmt::string_view fmtString) noexcept; - - static void vformat_to(MemoryBuffer& out, fmt::string_view fmt, fmt::format_args args); - - static size_t formatted_size(fmt::string_view fmt, fmt::format_args args); - - static void vformat_to(char* out, fmt::string_view fmt, fmt::format_args args); - - static typename SPSCVarQueueOPT::MsgHeader* allocMsg(uint32_t size, bool logQFullCB) noexcept; - - TSCNS tscns; - - volatile LogLevel currentLogLevel; - static FAST_THREAD_LOCAL ThreadBuffer* threadBuffer; - - template - static inline constexpr bool isNamedArg() { - return fmt::detail::is_named_arg>::value; - } - - template - struct unNamedType - { using type = Arg; }; - - template - struct unNamedType> - { using type = Arg; }; - -#if FMT_USE_NONTYPE_TEMPLATE_ARGS - template Str> - struct unNamedType> - { using type = Arg; }; -#endif - - template - static inline constexpr bool isCstring() { - return fmt::detail::mapped_type_constant::value == - fmt::detail::type::cstring_type; - } - - template - static inline constexpr bool isString() { - return fmt::detail::mapped_type_constant::value == fmt::detail::type::string_type; - } - - template - static inline constexpr bool needCallDtor() { - using ArgType = fmt::remove_cvref_t; - if constexpr (isNamedArg()) { - return needCallDtor::type>(); - } - if constexpr (isString()) return false; - return !std::is_trivially_destructible::value; - } - - template - static inline constexpr size_t getArgSizes(size_t* cstringSize) { - return 0; - } - - template - static inline constexpr size_t getArgSizes(size_t* cstringSize, const Arg& arg, - const Args&... args) { - if constexpr (isNamedArg()) { - return getArgSizes(cstringSize, arg.value, args...); - } - else if constexpr (isCstring()) { - size_t len = strlen(arg) + 1; - cstringSize[CstringIdx] = len; - return len + getArgSizes(cstringSize, args...); - } - else if constexpr (isString()) { - size_t len = arg.size() + 1; - return len + getArgSizes(cstringSize, args...); - } - else { - return sizeof(Arg) + getArgSizes(cstringSize, args...); - } - } - - template - static inline constexpr char* encodeArgs(size_t* cstringSize, char* out) { - return out; - } - - template - static inline constexpr char* encodeArgs(size_t* cstringSize, char* out, Arg&& arg, - Args&&... args) { - if constexpr (isNamedArg()) { - return encodeArgs(cstringSize, out, arg.value, std::forward(args)...); - } - else if constexpr (isCstring()) { - memcpy(out, arg, cstringSize[CstringIdx]); - return encodeArgs(cstringSize, out + cstringSize[CstringIdx], - std::forward(args)...); - } - else if constexpr (isString()) { - size_t len = arg.size(); - memcpy(out, arg.data(), len); - out[len] = 0; - return encodeArgs(cstringSize, out + len + 1, std::forward(args)...); - } - else { - // If Arg has alignment >= 16, gcc could emit aligned move instructions(e.g. movdqa) for - // placement new even if the *out* is misaligned, which would cause segfault. So we use memcpy - // when possible - if constexpr (std::is_trivially_copyable_v>) { - memcpy(out, &arg, sizeof(Arg)); - } - else { - new (out) fmt::remove_cvref_t(std::forward(arg)); - } - return encodeArgs(cstringSize, out + sizeof(Arg), std::forward(args)...); - } - } - - template - static inline constexpr void storeNamedArgs(fmt::detail::named_arg_info* named_args_store) { - } - - template - static inline constexpr void storeNamedArgs(fmt::detail::named_arg_info* named_args_store, - const Arg& arg, const Args&... args) { - if constexpr (isNamedArg()) { - named_args_store[NamedIdx] = {arg.name, Idx}; - storeNamedArgs(named_args_store, args...); - } - else { - storeNamedArgs(named_args_store, args...); - } - } - - template - static inline const char* decodeArgs(const char* in, fmt::basic_format_arg* args, - const char** destruct_args) { - return in; - } - - template - static inline const char* decodeArgs(const char* in, fmt::basic_format_arg* args, - const char** destruct_args) { - using namespace fmtlogdetail; - using ArgType = fmt::remove_cvref_t; - if constexpr (isNamedArg()) { - return decodeArgs::type, Args...>( - in, args, destruct_args); - } - else if constexpr (isCstring() || isString()) { - size_t size = strlen(in); - fmt::string_view v(in, size); - if constexpr (ValueOnly) { - fmt::detail::value& value_ = *(fmt::detail::value*)(args + Idx); - value_ = fmt::detail::arg_mapper().map(v); - } - else { - args[Idx] = fmt::detail::make_arg(v); - } - return decodeArgs(in + size + 1, args, - destruct_args); - } - else { - if constexpr (ValueOnly) { - fmt::detail::value& value_ = *(fmt::detail::value*)(args + Idx); - if constexpr (UnrefPtr::value) { - value_ = fmt::detail::arg_mapper().map(**(ArgType*)in); - } - else { - value_ = fmt::detail::arg_mapper().map(*(ArgType*)in); - } - } - else { - if constexpr (UnrefPtr::value) { - args[Idx] = fmt::detail::make_arg(**(ArgType*)in); - } - else { - args[Idx] = fmt::detail::make_arg(*(ArgType*)in); - } - } - - if constexpr (needCallDtor()) { - destruct_args[DestructIdx] = in; - return decodeArgs(in + sizeof(ArgType), args, - destruct_args); - } - else { - return decodeArgs(in + sizeof(ArgType), args, - destruct_args); - } - } - } - - template - static inline void destructArgs(const char** destruct_args) {} - - template - static inline void destructArgs(const char** destruct_args) { - using ArgType = fmt::remove_cvref_t; - if constexpr (isNamedArg()) { - destructArgs::type, Args...>(destruct_args); - } - else if constexpr (needCallDtor()) { - ((ArgType*)destruct_args[DestructIdx])->~ArgType(); - destructArgs(destruct_args); - } - else { - destructArgs(destruct_args); - } - } - - template - static const char* formatTo(fmt::string_view format, const char* data, MemoryBuffer& out, - int& argIdx, std::vector>& args) { - constexpr size_t num_args = sizeof...(Args); - constexpr size_t num_dtors = fmt::detail::count()...>(); - const char* dtor_args[(std::max)(num_dtors, (size_t)1)]; - const char* ret; - if (argIdx < 0) { - argIdx = (int)args.size(); - args.resize(argIdx + num_args); - ret = decodeArgs(data, args.data() + argIdx, dtor_args); - } - else { - ret = decodeArgs(data, args.data() + argIdx, dtor_args); - } - vformat_to(out, format, fmt::basic_format_args(args.data() + argIdx, num_args)); - destructArgs<0, Args...>(dtor_args); - - return ret; - } - - template - static fmt::string_view unNameFormat(fmt::string_view in, uint32_t* reorderIdx, - const Args&... args) { - constexpr size_t num_named_args = fmt::detail::count()...>(); - if constexpr (num_named_args == 0) { - return in; - } - const char* begin = in.data(); - const char* p = begin; - std::unique_ptr unnamed_str(new char[in.size() + 1 + num_named_args * 5]); - fmt::detail::named_arg_info named_args[(std::max)(num_named_args, (size_t)1)]; - storeNamedArgs<0, 0>(named_args, args...); - - char* out = (char*)unnamed_str.get(); - uint8_t arg_idx = 0; - while (true) { - auto c = *p++; - if (!c) { - size_t copy_size = p - begin - 1; - memcpy(out, begin, copy_size); - out += copy_size; - break; - } - if (c != '{') continue; - size_t copy_size = p - begin; - memcpy(out, begin, copy_size); - out += copy_size; - begin = p; - c = *p++; - if (!c) fmt::detail::throw_format_error("invalid format string"); - if (fmt::detail::is_name_start(c)) { - while ((fmt::detail::is_name_start(c = *p) || ('0' <= c && c <= '9'))) { - ++p; - } - fmt::string_view name(begin, p - begin); - int id = -1; - for (size_t i = 0; i < num_named_args; ++i) { - if (named_args[i].name == name) { - id = named_args[i].id; - break; - } - } - if (id < 0) fmt::detail::throw_format_error("invalid format string"); - if constexpr (Reorder) { - reorderIdx[id] = arg_idx++; - } - else { - out = fmt::format_to(out, "{}", id); - } - } - else { - *out++ = c; - } - begin = p; - } - const char* ptr = unnamed_str.release(); - return fmt::string_view(ptr, out - ptr); - } - -public: - template - inline void log( - uint32_t& logId, int64_t tsc, const char* location, LogLevel level, - fmt::format_string>::type...> format, - Args&&... args) noexcept { - if (!logId) { - auto unnamed_format = unNameFormat(fmt::string_view(format), nullptr, args...); - registerLogInfo(logId, formatTo, location, level, unnamed_format); - } - constexpr size_t num_cstring = fmt::detail::count()...>(); - size_t cstringSizes[(std::max)(num_cstring, (size_t)1)]; - uint32_t alloc_size = 8 + (uint32_t)getArgSizes<0>(cstringSizes, args...); - bool q_full_cb = true; - do { - if (auto header = allocMsg(alloc_size, q_full_cb)) { - header->logId = logId; - char* out = (char*)(header + 1); - *(int64_t*)out = tsc; - out += 8; - encodeArgs<0>(cstringSizes, out, std::forward(args)...); - header->push(alloc_size); - break; - } - q_full_cb = false; - } while (FMTLOG_BLOCK); - } - - template - inline void logOnce(const char* location, LogLevel level, fmt::format_string format, - Args&&... args) { - fmt::string_view sv(format); - auto&& fmt_args = fmt::make_format_args(args...); - uint32_t fmt_size = formatted_size(sv, fmt_args); - uint32_t alloc_size = 8 + 8 + fmt_size; - bool q_full_cb = true; - do { - if (auto header = allocMsg(alloc_size, q_full_cb)) { - header->logId = (uint32_t)level; - char* out = (char*)(header + 1); - *(int64_t*)out = tscns.rdtsc(); - out += 8; - *(const char**)out = location; - out += 8; - vformat_to(out, sv, fmt_args); - header->push(alloc_size); - break; - } - q_full_cb = false; - } while (FMTLOG_BLOCK); - } -}; - -using fmtlog = fmtlogT<>; - -template -FAST_THREAD_LOCAL typename fmtlogT<_>::ThreadBuffer* fmtlogT<_>::threadBuffer; - -template -struct fmtlogWrapper -{ static fmtlog impl; }; - -template -fmtlog fmtlogWrapper<_>::impl; - -template -inline void fmtlogT<_>::setLogLevel(LogLevel logLevel) noexcept { - fmtlogWrapper<>::impl.currentLogLevel = logLevel; -} - -template -inline typename fmtlogT<_>::LogLevel fmtlogT<_>::getLogLevel() noexcept { - return fmtlogWrapper<>::impl.currentLogLevel; -} - -template -inline bool fmtlogT<_>::checkLogLevel(LogLevel logLevel) noexcept { -#ifdef FMTLOG_NO_CHECK_LEVEL - return true; -#else - return logLevel >= fmtlogWrapper<>::impl.currentLogLevel; -#endif -} - -#define __FMTLOG_S1(x) #x -#define __FMTLOG_S2(x) __FMTLOG_S1(x) -#define __FMTLOG_LOCATION __FILE__ ":" __FMTLOG_S2(__LINE__) - -#define FMTLOG(level, format, ...) \ - do { \ - static uint32_t logId = 0; \ - if (!fmtlog::checkLogLevel(level)) break; \ - fmtlogWrapper<>::impl.log(logId, fmtlogWrapper<>::impl.tscns.rdtsc(), __FMTLOG_LOCATION, \ - level, format, ##__VA_ARGS__); \ - } while (0) - -#define FMTLOG_LIMIT(min_interval, level, format, ...) \ - do { \ - static uint32_t logId = 0; \ - static int64_t limitNs = 0; \ - if (!fmtlog::checkLogLevel(level)) break; \ - int64_t tsc = fmtlogWrapper<>::impl.tscns.rdtsc(); \ - int64_t ns = fmtlogWrapper<>::impl.tscns.tsc2ns(tsc); \ - if (ns < limitNs) break; \ - limitNs = ns + min_interval; \ - fmtlogWrapper<>::impl.log(logId, tsc, __FMTLOG_LOCATION, level, format, ##__VA_ARGS__); \ - } while (0) - -#define FMTLOG_ONCE(level, format, ...) \ - do { \ - if (!fmtlog::checkLogLevel(level)) break; \ - fmtlogWrapper<>::impl.logOnce(__FMTLOG_LOCATION, level, format, ##__VA_ARGS__); \ - } while (0) - -#if FMTLOG_ACTIVE_LEVEL <= FMTLOG_LEVEL_DBG -#define logd(format, ...) FMTLOG(fmtlog::DBG, format, ##__VA_ARGS__) -#define logdo(format, ...) FMTLOG_ONCE(fmtlog::DBG, format, ##__VA_ARGS__) -#define logdl(min_interval, format, ...) FMTLOG_LIMIT(min_interval, fmtlog::DBG, format, ##__VA_ARGS__) -#else -#define logd(format, ...) (void)0 -#define logdo(format, ...) (void)0 -#define logdl(min_interval, format, ...) (void)0 -#endif - -#if FMTLOG_ACTIVE_LEVEL <= FMTLOG_LEVEL_INF -#define logi(format, ...) FMTLOG(fmtlog::INF, format, ##__VA_ARGS__) -#define logio(format, ...) FMTLOG_ONCE(fmtlog::INF, format, ##__VA_ARGS__) -#define logil(min_interval, format, ...) FMTLOG_LIMIT(min_interval, fmtlog::INF, format, ##__VA_ARGS__) -#else -#define logi(format, ...) (void)0 -#define logio(format, ...) (void)0 -#define logil(min_interval, format, ...) (void)0 -#endif - -#if FMTLOG_ACTIVE_LEVEL <= FMTLOG_LEVEL_WRN -#define logw(format, ...) FMTLOG(fmtlog::WRN, format, ##__VA_ARGS__) -#define logwo(format, ...) FMTLOG_ONCE(fmtlog::WRN, format, ##__VA_ARGS__) -#define logwl(min_interval, format, ...) FMTLOG_LIMIT(min_interval, fmtlog::WRN, format, ##__VA_ARGS__) -#else -#define logw(format, ...) (void)0 -#define logwo(format, ...) (void)0 -#define logwl(min_interval, format, ...) (void)0 -#endif - -#if FMTLOG_ACTIVE_LEVEL <= FMTLOG_LEVEL_ERR -#define loge(format, ...) FMTLOG(fmtlog::ERR, format, ##__VA_ARGS__) -#define logeo(format, ...) FMTLOG_ONCE(fmtlog::ERR, format, ##__VA_ARGS__) -#define logel(min_interval, format, ...) FMTLOG_LIMIT(min_interval, fmtlog::ERR, format, ##__VA_ARGS__) -#else -#define loge(format, ...) (void)0 -#define logeo(format, ...) (void)0 -#define logel(min_interval, format, ...) (void)0 -#endif - -#ifdef FMTLOG_HEADER_ONLY -#include "fmtlog-inl.h" -#endif diff --git a/NetTunnelSDK/misc.cpp b/NetTunnelSDK/misc.cpp new file mode 100644 index 0000000..7bd3123 --- /dev/null +++ b/NetTunnelSDK/misc.cpp @@ -0,0 +1,85 @@ +#include "pch.h" +#include "misc.h" +#include "usrerr.h" + +#include +#include + + +void RemoveTailLineBreak(TCHAR* pInputStr, int strSize) +{ + size_t length; + if (pInputStr) + { + if (StringCbLength(pInputStr, strSize, &length) == S_OK && length > 0) + { + if (pInputStr[length - 2] == '\r' && pInputStr[length - 1] == '\n') + { + pInputStr[length - 2] = pInputStr[length - 1] = 0; + } + else if (pInputStr[length - 1] == '\n') + { + pInputStr[length - 1] = 0; + } + } + } +} + +int RunPipeCmd(TCHAR* pszCmd, TCHAR* pszResultBuffer, int dwResultBufferSize) +{ + BOOL bRet; + HANDLE hReadPipe = nullptr; + HANDLE hWritePipe = nullptr; + STARTUPINFO si; + PROCESS_INFORMATION pi; + SECURITY_ATTRIBUTES securityAttributes; + + memset(&securityAttributes, 0, sizeof(SECURITY_ATTRIBUTES)); + memset(&si, 0, sizeof(STARTUPINFO)); + memset(&pi, 0, sizeof(PROCESS_INFORMATION)); + + // 设定管道的安全属性 + securityAttributes.bInheritHandle = TRUE; + securityAttributes.nLength = sizeof(securityAttributes); + securityAttributes.lpSecurityDescriptor = nullptr; + + // 创建匿名管道 + bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0); + if (FALSE == bRet) + { + SPDLOG_ERROR(TEXT("CreatePipe Error")); + return -ERR_SYS_CALL; + } + + // 设置新进程参数 + si.cb = sizeof(si); + si.hStdError = hWritePipe; + si.hStdOutput = hWritePipe; + si.wShowWindow = SW_HIDE; + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + + // 创建新进程执行命令, 将执行结果写入匿名管道中 + bRet = ::CreateProcess(nullptr, (pszCmd), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi); + if (FALSE == bRet) + { + SPDLOG_ERROR(TEXT("CreateProcess Error")); + } + + // 等待命令执行结束 + ::WaitForSingleObject(pi.hThread, INFINITE); + ::WaitForSingleObject(pi.hProcess, INFINITE); + + // 从匿名管道中读取结果到输出缓冲区 + ::RtlZeroMemory(pszResultBuffer, dwResultBufferSize); + ::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, nullptr, nullptr); + + // 关闭句柄, 释放内存 + ::CloseHandle(pi.hThread); + ::CloseHandle(pi.hProcess); + ::CloseHandle(hWritePipe); + ::CloseHandle(hReadPipe); + + RemoveTailLineBreak(pszResultBuffer, dwResultBufferSize); + //pszResultBuffer[dwResultBufferSize - 1] = 0; + return ERR_SUCCESS; +} diff --git a/NetTunnelSDK/misc.h b/NetTunnelSDK/misc.h index d83c3df..cfd97c2 100644 --- a/NetTunnelSDK/misc.h +++ b/NetTunnelSDK/misc.h @@ -1,10 +1,18 @@ #pragma once +#include + #ifndef ARRAY_SIZE -//#ifdef __cplusplus #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -//#else -//#define ARRAY_SIZE_TYPE_CHECK(a) (sizeof(typeof(int[1 - 2 * !!__builtin_types_compatible_p(typeof(a), typeof(&a[0]))]))) -//#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]) + ARRAY_SIZE_TYPE_CHECK(a) * 0) -//#endif -#endif \ No newline at end of file +#endif + +#ifdef __cplusplus // If used by C++ code, +extern "C" { +// we need to export the C interface +#endif + +void RemoveTailLineBreak(TCHAR* pInputStr, int strSize); +int RunPipeCmd(TCHAR* pszCmd, TCHAR* pszResultBuffer, int dwResultBufferSize); +#ifdef __cplusplus +} +#endif diff --git a/NetTunnelSDK/network.cpp b/NetTunnelSDK/network.cpp new file mode 100644 index 0000000..bc28f87 --- /dev/null +++ b/NetTunnelSDK/network.cpp @@ -0,0 +1,78 @@ +#include "pch.h" +#include "tunnel.h" +#include "usrerr.h" +#include +#include +#include +#include + +#include "globalcfg.h" + +#pragma comment(lib,"Iphlpapi.lib") + +TUNNEL_API int GetAllNICInfo(PNIC_CONTENT pInfo, int* pItemCounts) +{ + int nRel, id = 0; + IP_ADDR_STRING* pIpAddrString; + PIP_ADAPTER_INFO pIpAdapterInfo; + unsigned long stSize; + + if (pItemCounts == nullptr || pInfo == nullptr) + { + return -ERR_INPUT_PARAMS; + } + + pIpAdapterInfo = new IP_ADAPTER_INFO[NET_CARD_MAX]; + stSize = sizeof(IP_ADAPTER_INFO) * NET_CARD_MAX; + + // WIN32 API get net card information + nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize); + + if (ERROR_BUFFER_OVERFLOW == nRel) + { + delete[] pIpAdapterInfo; + return -ERR_MALLOC_MEMORY; + } + + PIP_ADAPTER_INFO cur = pIpAdapterInfo; + + while (cur) + { + StringCbCopy(pInfo[id].NetCardName, MAX_PATH, cur->AdapterName); + StringCbCopy(pInfo[id].NetCardDescription, MAX_PATH, cur->Description); + + switch (cur->Type) + { + case MIB_IF_TYPE_ETHERNET: + pIpAddrString = &(cur->IpAddressList); + StringCbCopy(pInfo[id].NetCardIpaddr, MAX_PATH, pIpAddrString->IpAddress.String); + StringCbCopy(pInfo[id].NetCardNetmask, MAX_PATH, pIpAddrString->IpMask.String); + break; + case MIB_IF_TYPE_OTHER: + case MIB_IF_TYPE_TOKENRING: + case MIB_IF_TYPE_FDDI: + case MIB_IF_TYPE_PPP: + case MIB_IF_TYPE_LOOPBACK: + case MIB_IF_TYPE_SLIP: + break; + default: // WIFI ,Unknown type + pIpAddrString = &(cur->IpAddressList); + StringCbCopy(pInfo[id].NetCardIpaddr, MAX_PATH, pIpAddrString->IpAddress.String); + StringCbCopy(pInfo[id].NetCardNetmask, MAX_PATH, pIpAddrString->IpMask.String); + break; + } + + StringCbPrintf(pInfo[id].NetCardMacAddr, MAX_PATH, "%02X:%02X:%02X:%02X:%02X:%02X", + cur->Address[0], cur->Address[1], cur->Address[2], cur->Address[3], cur->Address[4], + cur->Address[5]); + + id++; + cur = cur->Next; + } + + *pItemCounts = id; + + delete[] pIpAdapterInfo; + + return ERR_SUCCESS; +} diff --git a/NetTunnelSDK/packages.config b/NetTunnelSDK/packages.config index 7ee1a22..8f2695c 100644 --- a/NetTunnelSDK/packages.config +++ b/NetTunnelSDK/packages.config @@ -1,4 +1,5 @@  + - + \ No newline at end of file diff --git a/NetTunnelSDK/pch.h b/NetTunnelSDK/pch.h index 9660927..95f726c 100644 --- a/NetTunnelSDK/pch.h +++ b/NetTunnelSDK/pch.h @@ -10,4 +10,5 @@ // 添加要在此处预编译的标头 #include "framework.h" +#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_TRACE #endif //PCH_H diff --git a/NetTunnelSDK/tunnel.cpp b/NetTunnelSDK/tunnel.cpp index cf9ea82..7624480 100644 --- a/NetTunnelSDK/tunnel.cpp +++ b/NetTunnelSDK/tunnel.cpp @@ -1,66 +1,138 @@ #include "pch.h" #include "tunnel.h" -#include +#include +#include +#include +#include +#include #include "usrerr.h" -#include "logs/fmtlog.h" - -typedef struct -{ - PROTO_CRYPTO_TYPE proCryptoType; - char proKeyBuf[CRYPTO_MAX][256]; - fmtlog::LogLevel logLevel; -} SDK_CONFIG, *PSDK_CONFIG; +#include "globalcfg.h" +#include "misc.h" static SDK_CONFIG g_globalConfig; -NETTUNNELSDK_API int TunnelSDKInitEnv() +PSDK_CONFIG GetGlobalCfgInfo() { + return &g_globalConfig; +} + +TUNNEL_API int TunnelSDKInitEnv(const TCHAR* pWorkDir) +{ + size_t length; + spdlog::level::level_enum lv = g_globalConfig.logLevel; + memset(&g_globalConfig, 0, sizeof(SDK_CONFIG)); - g_globalConfig.logLevel = fmtlog::OFF; + g_globalConfig.logLevel = lv; + + + if (pWorkDir == nullptr) + { + // 获取当前文件默认路径 + GetCurrentDirectory(MAX_PATH, g_globalConfig.workDirectory); + } + else + { + if (StringCbLengthA(pWorkDir, MAX_PATH, &length) == S_OK && length == 0) + { + GetCurrentDirectory(MAX_PATH, g_globalConfig.workDirectory); + } + else + { + StringCbCopy(g_globalConfig.workDirectory, MAX_PATH, pWorkDir); + } + } + + if (FindWireguardExe(NULL, 0) != ERR_SUCCESS) + { + SPDLOG_ERROR(TEXT("WireGuard not found, Please install WireGuard first or set the WireGuard Path.")); + return -ERR_ITEM_EXISTS; + } + return ERR_SUCCESS; } -NETTUNNELSDK_API void InitTunnelSDKLog(const char* pLogFile, LOG_LEVEL level) +TUNNEL_API void TunnelSDKUnInit() { - char buf[MAX_PATH] = {0}; - static fmtlog::LogLevel lv[LOG_MAX] = {fmtlog::DBG, fmtlog::INF, fmtlog::WRN, fmtlog::ERR,}; +} + +static spdlog::level::level_enum logLevelToSpdlogLevel(LOG_LEVEL level) +{ + switch (level) + { + case LOG_TRACE: + return spdlog::level::level_enum::trace; + case LOG_DEBUG: + return spdlog::level::level_enum::debug; + case LOG_INFO: + return spdlog::level::level_enum::info; + case LOG_WARN: + return spdlog::level::level_enum::warn; + case LOG_ERROR: + return spdlog::level::level_enum::err; + case LOG_CRITICAL: + return spdlog::level::level_enum::critical; + default: + return spdlog::level::level_enum::info; + } +} + +TUNNEL_API void InitTunnelSDKLog(const TCHAR* pLogFile, LOG_LEVEL level) +{ + TCHAR buf[MAX_PATH] = {0}; //::MessageBoxA(NULL, pLogFile, NULL, MB_OK); if (pLogFile && strlen(pLogFile) > 0) { - strncpy_s(buf, pLogFile, MAX_PATH); + StringCbCopy(buf, MAX_PATH, pLogFile); } else { - GetCurrentDirectory(MAX_PATH, buf); - strcat_s(buf, "\\tunnelsdk.log"); + StringCbCopy(buf, MAX_PATH, TEXT("tunnelsdk.log")); } - fmtlog::setLogFile(buf, false); - fmtlog::setHeaderPattern("[{YmdHMSe}][{l}][{s}] "); - fmtlog::setFlushDelay(1000000); - fmtlog::setLogLevel(lv[level]); + g_globalConfig.logLevel = logLevelToSpdlogLevel(level); - g_globalConfig.logLevel = lv[level]; + auto dupFileFilter = std::make_shared(std::chrono::seconds(5)); + auto dupStdFilter = std::make_shared(std::chrono::seconds(5)); - FMTLOG(lv[level], "Log({1}):{0}", buf, (int)level); + dupFileFilter->add_sink(std::make_shared(buf, 1024 * 1024 * 5, 10)); + dupStdFilter->add_sink(std::make_shared()); + + std::vector sinks{dupStdFilter, dupFileFilter}; + auto logger = std::make_shared(TEXT("tunnelSDK"), sinks.begin(), sinks.end()); + spdlog::set_default_logger(logger); + + spdlog::set_level(g_globalConfig.logLevel); + spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l][%s:%#] %v"); + spdlog::flush_every(std::chrono::seconds(1)); + +#if 0 + std::cout << "TRACE: " << logger->should_log(spdlog::level::trace) << std::endl; + std::cout << "DEBUG: " << logger->should_log(spdlog::level::debug) << std::endl; + std::cout << "INFO: " << logger->should_log(spdlog::level::info) << std::endl; + std::cout << "WARN: " << logger->should_log(spdlog::level::warn) << std::endl; + std::cout << "ERROR: " << logger->should_log(spdlog::level::err) << std::endl; + std::cout << "CRITICAL: " << logger->should_log(spdlog::level::critical) << std::endl; +#endif + + SPDLOG_INFO(TEXT("Log({1}): {0}"), buf, static_cast(level)); } -NETTUNNELSDK_API void TunnelLogEnable(bool enLog) +TUNNEL_API void TunnelLogEnable(bool enLog) { if (enLog) { - fmtlog::setLogLevel(g_globalConfig.logLevel); + spdlog::set_level(g_globalConfig.logLevel); } else { - fmtlog::setLogLevel(fmtlog::OFF); + spdlog::set_level(spdlog::level::level_enum::off); } } -NETTUNNELSDK_API int SetProtocolEncryptType(PROTO_CRYPTO_TYPE type, const char* pProKey) +TUNNEL_API int SetProtocolEncryptType(PROTO_CRYPTO_TYPE type, const TCHAR* pProKey) { if (type > CRYPTO_BASE64 && type < CRYPTO_MAX) { @@ -71,25 +143,26 @@ NETTUNNELSDK_API int SetProtocolEncryptType(PROTO_CRYPTO_TYPE type, const char* } g_globalConfig.proCryptoType = type; - strncpy_s(g_globalConfig.proKeyBuf[type], pProKey, 256); + StringCbCopy(g_globalConfig.proKeyBuf[type], 256, pProKey); - logd("Protocol crypto type: {0} with key [{1}]", (int)type, pProKey? pProKey : ""); + SPDLOG_DEBUG(TEXT("Protocol crypto type: {0} with key [{1}]"), static_cast(type), + pProKey ? pProKey : TEXT("")); return ERR_SUCCESS; } -NETTUNNELSDK_API int CreateTunnel(LPCSTR lpszMsg) +TUNNEL_API int CreateTunnel(LPCSTR lpszMsg) { OutputDebugStringA(lpszMsg); return 0; } -NETTUNNELSDK_API const char* TestMessage() +TUNNEL_API const TCHAR* TestMessage() { - return "Test Message"; + return TEXT("Test Message"); } -NETTUNNELSDK_API int Add(int a, int b) +TUNNEL_API int Add(int a, int b) { return a + b; } diff --git a/NetTunnelSDK/tunnel.h b/NetTunnelSDK/tunnel.h index 8e658ed..0951c0a 100644 --- a/NetTunnelSDK/tunnel.h +++ b/NetTunnelSDK/tunnel.h @@ -3,12 +3,15 @@ #include #ifdef NETTUNNELSDK_EXPORTS -#define NETTUNNELSDK_API __declspec(dllexport) +#define TUNNEL_API __declspec(dllexport) #else -#define NETTUNNELSDK_API __declspec(dllimport) +#define TUNNEL_API __declspec(dllimport) #endif -using PROTO_CRYPTO_TYPE = enum +#define WG_KEY_MAX (64) +#define NET_CARD_MAX (32) + +typedef enum { CRYPTO_NONE = 0, CRYPTO_BASE64 = 1, @@ -16,29 +19,46 @@ using PROTO_CRYPTO_TYPE = enum CRYPTO_3DES = 3, CRYPTO_AES256 = 4, CRYPTO_MAX, -}; +} PROTO_CRYPTO_TYPE; typedef enum { - LOG_DEBUG = 0, - LOG_INFO = 1, - LOG_WARN = 2, - LOG_ERROR = 3, + LOG_TRACE = 0, + LOG_DEBUG, + LOG_INFO, + LOG_WARN, + LOG_ERROR, + LOG_CRITICAL, LOG_MAX } LOG_LEVEL; +typedef struct +{ + TCHAR NetCardName[256]; + TCHAR NetCardDescription[256]; + TCHAR NetCardIpaddr[256]; + TCHAR NetCardNetmask[256]; + TCHAR NetCardMacAddr[256]; +} NIC_CONTENT, *PNIC_CONTENT; + + #ifdef __cplusplus // If used by C++ code, extern "C" { // we need to export the C interface #endif -NETTUNNELSDK_API int __cdecl CreateTunnel(LPCSTR lpszMsg); -NETTUNNELSDK_API const char* __cdecl TestMessage(); -NETTUNNELSDK_API int __cdecl Add(int a, int b); -NETTUNNELSDK_API int __cdecl TunnelSDKInitEnv(); -NETTUNNELSDK_API int __cdecl SetProtocolEncryptType(PROTO_CRYPTO_TYPE type, const char* pProKey); -NETTUNNELSDK_API void __cdecl InitTunnelSDKLog(const char* pLogFile, LOG_LEVEL level); -NETTUNNELSDK_API void __cdecl TunnelLogEnable(bool enLog); +TUNNEL_API int __cdecl CreateTunnel(LPCSTR lpszMsg); +TUNNEL_API const TCHAR* __cdecl TestMessage(); +TUNNEL_API int __cdecl Add(int a, int b); +TUNNEL_API int __cdecl TunnelSDKInitEnv(const TCHAR* pWorkDir); +TUNNEL_API int __cdecl SetProtocolEncryptType(PROTO_CRYPTO_TYPE type, const TCHAR* pProKey); +TUNNEL_API void __cdecl InitTunnelSDKLog(const TCHAR* pLogFile, LOG_LEVEL level); +TUNNEL_API void __cdecl TunnelLogEnable(bool enLog); +TUNNEL_API int __cdecl FindWireguardExe(TCHAR* pFullPath, int maxSize); +TUNNEL_API int __cdecl SetWireguardPath(TCHAR* pPath); +TUNNEL_API void __cdecl TunnelSDKUnInit(); +TUNNEL_API int __cdecl GenerateWireguardKeyPairs(TCHAR* pPubKey, int pubkeySize, TCHAR* pPrivKey, int privKeySize); +TUNNEL_API int __cdecl GetAllNICInfo(PNIC_CONTENT pInfo, int* pItemCounts); #ifdef __cplusplus } diff --git a/NetTunnelSDK/usrerr.cpp b/NetTunnelSDK/usrerr.cpp index 556692d..3ed2fb1 100644 --- a/NetTunnelSDK/usrerr.cpp +++ b/NetTunnelSDK/usrerr.cpp @@ -5,24 +5,29 @@ #define GENERATE_STRING(STRING,x, desc) {#STRING, desc}, -static const char *g_enumStrVal[][MAX_DESC_LENGTH] = { +static const char* g_enumStrVal[][MAX_DESC_LENGTH] = { DEF_ERR_CODE(GENERATE_STRING) {"ERR_UNKNOWN", "未知错误"}, }; -const char *getErrorEnumNameString(int errCode) { - if (errCode < 0) { +const char* getErrorEnumNameString(int errCode) +{ + if (errCode < 0) + { errCode = -errCode; } - if (errCode >= ARRAY_SIZE(g_enumStrVal) || errCode < 0) { + if (errCode >= ARRAY_SIZE(g_enumStrVal) || errCode < 0) + { return g_enumStrVal[ARRAY_SIZE(g_enumStrVal) - 1][0]; } return g_enumStrVal[errCode][0]; } -const char *getErrorEnumDesc(int errCode) { - if (errCode >= ARRAY_SIZE(g_enumStrVal) || errCode < 0) { +const char* getErrorEnumDesc(int errCode) +{ + if (errCode >= ARRAY_SIZE(g_enumStrVal) || errCode < 0) + { return g_enumStrVal[ARRAY_SIZE(g_enumStrVal) - 1][0]; } return g_enumStrVal[errCode][1]; -} \ No newline at end of file +} diff --git a/NetTunnelSDK/usrerr.h b/NetTunnelSDK/usrerr.h index ac38100..235118c 100644 --- a/NetTunnelSDK/usrerr.h +++ b/NetTunnelSDK/usrerr.h @@ -19,6 +19,7 @@ ERR_CODE(ERR_MALLOC_MEMORY, 14, "分配内存失败") \ ERR_CODE(ERR_MMAP_MEMORY, 15, "共享内存失败") + #define GENERATE_ENUM(ENUM, n, x) ENUM, typedef enum diff --git a/NetTunnelSDK/wireguard.cpp b/NetTunnelSDK/wireguard.cpp index bcb5590..ce8e3e0 100644 --- a/NetTunnelSDK/wireguard.cpp +++ b/NetTunnelSDK/wireguard.cpp @@ -1 +1,230 @@ #include "pch.h" +#include "tunnel.h" +#include "usrerr.h" +#include +#include + +#include "globalcfg.h" +#include "misc.h" + +#define WINENVBUF_SIZE (4096) +#define CONFIG_FILE_NAME TEXT("tunnelsdk.ini") +#define CFG_WIREGUARD_SECTION TEXT("WireGuard") +#define CFG_WIREGUARD_PATH TEXT("WireGuardExe") +#define CFG_WG_PATH TEXT("WgExe") + + +TUNNEL_API int GenerateWireguardKeyPairs(TCHAR* pPubKey, int pubkeySize, TCHAR* pPrivKey, int privKeySize) +{ + int ret; + TCHAR cmdBuffer[MAX_PATH]; + TCHAR cmdResult[MAX_PATH]; + PSDK_CONFIG pCfg = GetGlobalCfgInfo(); + + // WireGuard 不存在或者未配置目录 + if (!pCfg->wireguardCfg.wgExists || !pCfg->wireguardCfg.wireguardExists) + { + return -ERR_ITEM_UNEXISTS; + } + + memset(cmdBuffer, 0, MAX_PATH); + memset(cmdResult, 0, MAX_PATH); + + StringCbPrintf(cmdBuffer, MAX_PATH, TEXT("cmd.exe /C \"%s\" genkey"), pCfg->wireguardCfg.wgPath); + + if ((ret = RunPipeCmd(cmdBuffer, cmdResult, MAX_PATH)) != ERR_SUCCESS) + { + SPDLOG_ERROR("Run command [{0}] error: {1}", cmdBuffer, ret); + return -ERR_CALL_SHELL; + } + + SPDLOG_DEBUG("Run command [{0}] resutl \'{1}\'", cmdBuffer, cmdResult); + + StringCbCopy(pPrivKey, privKeySize, cmdResult); + memset(cmdBuffer, 0, MAX_PATH); + StringCbPrintf(cmdBuffer, MAX_PATH, TEXT("cmd.exe /C echo %s | \"%s\" pubkey"), cmdResult, + pCfg->wireguardCfg.wgPath); + + memset(cmdResult, 0, MAX_PATH); + if ((ret = RunPipeCmd(cmdBuffer, cmdResult, MAX_PATH)) != ERR_SUCCESS) + { + SPDLOG_ERROR("Run command [{0}] error: {1}", cmdBuffer, ret); + return -ERR_CALL_SHELL; + } + + StringCbCopy(pPubKey, pubkeySize, cmdResult); + SPDLOG_DEBUG("Run command [{0}] resutl \'{1}\'", cmdBuffer, cmdResult); + + return ERR_SUCCESS; +} + +TUNNEL_API int SetWireguardPath(TCHAR* pPath) +{ + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + + if (pPath == nullptr) + { + return -ERR_INPUT_PARAMS; + } + + hFind = FindFirstFile(pPath, &FindFileData); + + if (hFind != INVALID_HANDLE_VALUE) + { + TCHAR path[MAX_PATH] = {0}; + TCHAR wgPath[MAX_PATH]; + + StringCbPrintf(path, MAX_PATH, TEXT("%s\\%s"), GetGlobalCfgInfo()->workDirectory, CONFIG_FILE_NAME); + + SPDLOG_DEBUG(TEXT("Used configure file:{0}"), path); + + WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WIREGUARD_PATH, pPath, path); + SPDLOG_DEBUG(TEXT("Save configure: {1} --> {0}"), pPath, CFG_WIREGUARD_PATH); + + StringCbCopy(wgPath, MAX_PATH, pPath); + TCHAR* pIndex = _tcsrchr(wgPath, '\\'); + + if (pIndex) + { + *pIndex = 0; + StringCbCat(wgPath, MAX_PATH, "\\wg.exe"); + WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WG_PATH, wgPath, path); + SPDLOG_DEBUG(TEXT("Save configure: {1} --> {0}"), wgPath, CFG_WG_PATH); + } + + return ERR_SUCCESS; + } + else + { + return -ERR_ITEM_UNEXISTS; + } +} + +TUNNEL_API int FindWireguardExe(TCHAR* pFullPath, int maxSize) +{ + TCHAR path[MAX_PATH]; + TCHAR wrieguardPath[MAX_PATH]; + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + DWORD dwRet, dwErr; + LPSTR pEnvBuf; + TCHAR *token, *p = nullptr; + + memset(path, 0, MAX_PATH); + StringCbPrintf(path, MAX_PATH, TEXT("%s\\%s"), GetGlobalCfgInfo()->workDirectory, CONFIG_FILE_NAME); + GetPrivateProfileString(CFG_WIREGUARD_SECTION,CFG_WIREGUARD_PATH,TEXT(""), wrieguardPath,MAX_PATH, path); + + hFind = FindFirstFile(wrieguardPath, &FindFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + if (pFullPath && maxSize > 0) + { + StringCbCopy(pFullPath, maxSize, wrieguardPath); + } + + StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wireguardPath, MAX_PATH, wrieguardPath); + GetGlobalCfgInfo()->wireguardCfg.wireguardExists = TRUE; + + SPDLOG_DEBUG(TEXT("Ini found WireGuard at: {0}"), wrieguardPath); + + memset(path, 0, MAX_PATH); + StringCbPrintf(path, MAX_PATH, TEXT("%s\\%s"), GetGlobalCfgInfo()->workDirectory, CONFIG_FILE_NAME); + GetPrivateProfileString(CFG_WIREGUARD_SECTION,CFG_WG_PATH,TEXT(""), wrieguardPath,MAX_PATH, path); + + hFind = FindFirstFile(wrieguardPath, &FindFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wgPath, MAX_PATH, wrieguardPath); + GetGlobalCfgInfo()->wireguardCfg.wgExists = TRUE; + SPDLOG_DEBUG(TEXT("Ini found WireGuard Tools at: {0}"), wrieguardPath); + } + + return ERR_SUCCESS; + } + + pEnvBuf = static_cast(malloc(WINENVBUF_SIZE)); + if (nullptr == pEnvBuf) + { + SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), WINENVBUF_SIZE); + return -ERR_MALLOC_MEMORY; + } + + dwRet = GetEnvironmentVariable(TEXT("path"), pEnvBuf, WINENVBUF_SIZE); + + if (0 == dwRet) + { + dwErr = GetLastError(); + if (ERROR_ENVVAR_NOT_FOUND == dwErr) + { + SPDLOG_DEBUG(TEXT("Environment variable path does not exist.")); + free(pEnvBuf); + return -ERR_FILE_NOT_EXISTS; + } + } + else if (WINENVBUF_SIZE < dwRet) + { + pEnvBuf = static_cast(realloc(pEnvBuf, dwRet * sizeof(CHAR))); + if (nullptr == pEnvBuf) + { + SPDLOG_ERROR(TEXT("Malloc {0} bytes memory error"), dwRet * sizeof(CHAR)); + return -ERR_MALLOC_MEMORY; + } + dwRet = GetEnvironmentVariable("path", pEnvBuf, dwRet); + if (!dwRet) + { + SPDLOG_ERROR(TEXT("GetEnvironmentVariable failed (%d)"), GetLastError()); + free(pEnvBuf); + return -ERR_FILE_NOT_EXISTS; + } + } + + token = strtok_s(pEnvBuf, TEXT(";"), &p); + + while (token != nullptr) + { + memset(path, 0, MAX_PATH); + StringCbPrintfA(path, MAX_PATH, TEXT("%s\\wireguard.exe"), token); + + hFind = FindFirstFile(path, &FindFileData); + + if (hFind != INVALID_HANDLE_VALUE) + { + if (pFullPath && maxSize > 0) + { + StringCbCopy(pFullPath, maxSize, path); + } + + // 保存路径到配置文件 + SetWireguardPath(path); + SPDLOG_DEBUG(TEXT("Path Environment found WireGuard at: {0}"), path); + + StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wireguardPath, MAX_PATH, wrieguardPath); + GetGlobalCfgInfo()->wireguardCfg.wireguardExists = TRUE; + + memset(path, 0, MAX_PATH); + StringCbPrintf(path, MAX_PATH, TEXT("%s\\wg.exe"), token); + + SPDLOG_DEBUG(TEXT("Find WireGuard tools at: {0}"), path); + + hFind = FindFirstFile(path, &FindFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + StringCbCopy(GetGlobalCfgInfo()->wireguardCfg.wgPath, MAX_PATH, path); + GetGlobalCfgInfo()->wireguardCfg.wgExists = TRUE; + + SPDLOG_DEBUG(TEXT("Path Environment found WireGuard tools at: {0}"), path); + } + + + //TODO: throw exception by C# call, why?????? + //CloseHandle(hFind); + free(pEnvBuf); + return ERR_SUCCESS; + } + token = strtok_s(nullptr, TEXT(";"), &p); + } + + free(pEnvBuf); + return -ERR_FILE_NOT_EXISTS; +} diff --git a/TestNetTunnelSDK/TestNetTunnelSDK.cpp b/TestNetTunnelSDK/TestNetTunnelSDK.cpp new file mode 100644 index 0000000..691b029 --- /dev/null +++ b/TestNetTunnelSDK/TestNetTunnelSDK.cpp @@ -0,0 +1,67 @@ +#include "pch.h" +#include "CppUnitTest.h" +#include "../NetTunnelSDK/tunnel.h" +#include "../NetTunnelSDK/usrerr.h" +#include "../NetTunnelSDK/misc.h" + +using namespace Microsoft::VisualStudio::CppUnitTestFramework; + +namespace TestNetTunnelSDK +{ + TEST_MODULE_INITIALIZE(ModuleInitialize) + { + Logger::WriteMessage("In Module Initialize"); + TunnelSDKInitEnv(TEXT( + "C:\\Users\\HuangXin\\Documents\\development\\visual_studio\\tunnel_windows\\NetTunnelApp\\bin\\Debug")); + InitTunnelSDKLog( + TEXT( + "C:\\Users\\HuangXin\\Documents\\development\\visual_studio\\tunnel_windows\\NetTunnelApp\\bin\\Debug\\utest.log"), + LOG_DEBUG); + } + + TEST_MODULE_CLEANUP(ModuleCleanup) + { + Logger::WriteMessage("In Module Cleanup"); + TunnelSDKUnInit(); + } + + TEST_CLASS(TestNetTunnelSDK) + { + public: + TEST_METHOD(TestFindWireguardExe) + { + int ret = ERR_SUCCESS; + Assert::AreEqual(ret, FindWireguardExe(nullptr, 0)); + } + + TEST_METHOD(TestSetWireguardPath) + { + int ret = ERR_SUCCESS; + Assert::AreEqual(ret, SetWireguardPath(TEXT("C:\\Program Files\\WireGuard\\wireguard.exe"))); + } + + TEST_METHOD(TestRunPipeCmd) + { +#if 0 + TCHAR buf[1024]; + int ret = ERR_SUCCESS; + + Assert::AreEqual(ret, RunPipeCmd(TEXT("cmd.exe /C dir E:\\"), buf, 1024)); + Logger::WriteMessage("Return:"); + Logger::WriteMessage(buf); +#endif + } + + TEST_METHOD(TestGetAllNICInfo) + { + PNIC_CONTENT pInfo = (PNIC_CONTENT)malloc(sizeof(NIC_CONTENT) * 32); + + int size = 0; + int ret = ERR_SUCCESS; + + Assert::AreEqual(ret, GetAllNICInfo(pInfo, &size)); + + free(pInfo); + } + }; +} diff --git a/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj b/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj new file mode 100644 index 0000000..d10b963 --- /dev/null +++ b/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 17.0 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C} + Win32Proj + TestNetTunnelSDK + 10.0 + NativeUnitTestProject + + + + DynamicLibrary + true + v143 + Unicode + false + + + DynamicLibrary + false + v143 + true + Unicode + false + + + DynamicLibrary + true + v143 + MultiByte + false + + + DynamicLibrary + false + v143 + true + Unicode + false + + + + + + + + + + + + + + + + + + + + + true + + + true + + + false + + + false + + + + Use + Level3 + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + _DEBUG;%(PreprocessorDefinitions) + true + pch.h + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Use + Level3 + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;%(PreprocessorDefinitions) + true + pch.h + + + Windows + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Use + Level3 + true + true + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Use + Level3 + true + true + true + $(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories) + NDEBUG;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + true + $(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories) + + + + + Create + Create + Create + Create + + + + + + + + + {1584bad4-dbec-43d2-bc06-08c23f02489a} + + + + + + \ No newline at end of file diff --git a/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj.filters b/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj.filters new file mode 100644 index 0000000..37fa268 --- /dev/null +++ b/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + 源文件 + + + + + 头文件 + + + \ No newline at end of file diff --git a/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj.user b/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/TestNetTunnelSDK/TestNetTunnelSDK.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/TestNetTunnelSDK/pch.cpp b/TestNetTunnelSDK/pch.cpp new file mode 100644 index 0000000..b6fb8f4 --- /dev/null +++ b/TestNetTunnelSDK/pch.cpp @@ -0,0 +1,5 @@ +// pch.cpp: 与预编译标头对应的源文件 + +#include "pch.h" + +// 当使用预编译的头时,需要使用此源文件,编译才能成功。 diff --git a/TestNetTunnelSDK/pch.h b/TestNetTunnelSDK/pch.h new file mode 100644 index 0000000..69fcd40 --- /dev/null +++ b/TestNetTunnelSDK/pch.h @@ -0,0 +1,12 @@ +// pch.h: 这是预编译标头文件。 +// 下方列出的文件仅编译一次,提高了将来生成的生成性能。 +// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 +// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 +// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + +#ifndef PCH_H +#define PCH_H + +// 添加要在此处预编译的标头 + +#endif //PCH_H diff --git a/tunnel_windows.sln b/tunnel_windows.sln index f21ca20..bd8966b 100644 --- a/tunnel_windows.sln +++ b/tunnel_windows.sln @@ -10,6 +10,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetTunnelApp", "NetTunnelAp {1584BAD4-DBEC-43D2-BC06-08C23F02489A} = {1584BAD4-DBEC-43D2-BC06-08C23F02489A} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestNetTunnelSDK", "TestNetTunnelSDK\TestNetTunnelSDK.vcxproj", "{61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}" + ProjectSection(ProjectDependencies) = postProject + {1584BAD4-DBEC-43D2-BC06-08C23F02489A} = {1584BAD4-DBEC-43D2-BC06-08C23F02489A} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -44,6 +49,18 @@ Global {79995848-FD05-46F5-A7FE-46265E540E32}.Release|x64.Build.0 = Release|Any CPU {79995848-FD05-46F5-A7FE-46265E540E32}.Release|x86.ActiveCfg = Release|Any CPU {79995848-FD05-46F5-A7FE-46265E540E32}.Release|x86.Build.0 = Release|Any CPU + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Debug|Any CPU.ActiveCfg = Debug|x64 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Debug|Any CPU.Build.0 = Debug|x64 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Debug|x64.ActiveCfg = Debug|x64 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Debug|x64.Build.0 = Debug|x64 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Debug|x86.ActiveCfg = Debug|Win32 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Debug|x86.Build.0 = Debug|Win32 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Release|Any CPU.ActiveCfg = Release|x64 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Release|Any CPU.Build.0 = Release|x64 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Release|x64.ActiveCfg = Release|x64 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Release|x64.Build.0 = Release|x64 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Release|x86.ActiveCfg = Release|Win32 + {61FE87EB-A3BA-4A7E-971C-69CB05F5C81C}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE