diff --git a/NetTunnelApp/MainForm.cs b/NetTunnelApp/MainForm.cs index 1fe9be4..475c172 100644 --- a/NetTunnelApp/MainForm.cs +++ b/NetTunnelApp/MainForm.cs @@ -39,8 +39,9 @@ public partial class MainForm : Form 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("UUID:{0}", card.UUID); Console.WriteLine("Description:{0}", card.Description); + Console.WriteLine("Index:{0}", card.IfIndex); Console.WriteLine("Ip:{0}", card.IpAddr); Console.WriteLine("NetMask:{0}", card.NetMask); Console.WriteLine("MacAddr:{0}", card.MacAddr); @@ -109,12 +110,14 @@ public partial class MainForm : Form //var v = NetTunnelLib.FindWireguardExe(buffer, 256); //MessageBox.Show(buffer.ToString() + "----" + v.ToString()); - test_install_wg_server(); + //test_install_wg_server(); } private void button2_Click(object sender, EventArgs e) { - test_uninstall_wg_server(); + //test_uninstall_wg_server(); + + test_get_network_info(); } } \ No newline at end of file diff --git a/NetTunnelApp/NetTunnelLib.cs b/NetTunnelApp/NetTunnelLib.cs index 933d385..1d20403 100644 --- a/NetTunnelApp/NetTunnelLib.cs +++ b/NetTunnelApp/NetTunnelLib.cs @@ -27,18 +27,23 @@ public enum LogLevel [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct NetCard { + public int IfIndex; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] - public string Name; + public string UUID; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 132)] public string Description; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)] public string IpAddr; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)] public string NetMask; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 48)] + public string Gateway; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string MacAddr; } diff --git a/NetTunnelSDK/AIGCJson.hpp b/NetTunnelSDK/AIGCJson.hpp new file mode 100644 index 0000000..5484dd3 --- /dev/null +++ b/NetTunnelSDK/AIGCJson.hpp @@ -0,0 +1,1052 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace aigc +{ + +/****************************************************** + * Register class or struct members + * eg: + * struct Test + * { + * string A; + * string B; + * AIGC_JSON_HELPER(A, B) + * }; + ******************************************************/ +#define AIGC_JSON_HELPER(...) \ + std::map __aigcDefaultValues; \ + bool AIGCJsonToObject(aigc::JsonHelperPrivate &handle, \ + rapidjson::Value &jsonValue, \ + std::vector &names) \ + { \ + std::vector standardNames = handle.GetMembersNames(#__VA_ARGS__); \ + if (names.size() <= standardNames.size()) \ + { \ + for (int i = names.size(); i < (int)standardNames.size(); i++) \ + names.push_back(standardNames[i]); \ + } \ + return handle.SetMembers(names, 0, jsonValue, __aigcDefaultValues, __VA_ARGS__); \ + } \ + bool AIGCObjectToJson(aigc::JsonHelperPrivate &handle, \ + rapidjson::Value &jsonValue, \ + rapidjson::Document::AllocatorType &allocator, \ + std::vector &names) \ + { \ + std::vector standardNames = handle.GetMembersNames(#__VA_ARGS__); \ + if (names.size() <= standardNames.size()) \ + { \ + for (int i = names.size(); i < (int)standardNames.size(); i++) \ + names.push_back(standardNames[i]); \ + } \ + return handle.GetMembers(names, 0, jsonValue, allocator, __VA_ARGS__); \ + } + +/****************************************************** + * Rename members + * eg: + * struct Test + * { + * string A; + * string B; + * AIGC_JSON_HELPER(A, B) + * AIGC_JSON_HELPER_RENAME("a", "b") + * }; + ******************************************************/ +#define AIGC_JSON_HELPER_RENAME(...) \ + std::vector AIGCRenameMembers(aigc::JsonHelperPrivate &handle) \ + { \ + return handle.GetMembersNames(#__VA_ARGS__); \ + } + +/****************************************************** + * Register base-class + * eg: + * struct Base + * { + * string name; + * AIGC_JSON_HELPER(name) + * }; + * struct Test : Base + * { + * string A; + * string B; + * AIGC_JSON_HELPER(A, B) + * AIGC_JSON_HELPER_BASE((Base*)this) + * }; + ******************************************************/ +#define AIGC_JSON_HELPER_BASE(...) \ + bool AIGCBaseJsonToObject(aigc::JsonHelperPrivate &handle, \ + rapidjson::Value &jsonValue) \ + { \ + return handle.SetBase(jsonValue, __VA_ARGS__); \ + } \ + bool AIGCBaseObjectToJson(aigc::JsonHelperPrivate &handle, \ + rapidjson::Value &jsonValue, \ + rapidjson::Document::AllocatorType &allocator) \ + { \ + return handle.GetBase(jsonValue, allocator, __VA_ARGS__); \ + } + +/****************************************************** + * Set default value + * eg: + * struct Base + * { + * string name; + * int age; + * AIGC_JSON_HELPER(name, age) + * AIGC_JSON_HELPER_DEFAULT(age=18) + * }; + ******************************************************/ +#define AIGC_JSON_HELPER_DEFAULT(...) \ + void AIGCDefaultValues(aigc::JsonHelperPrivate &handle) \ + { \ + __aigcDefaultValues = handle.GetMembersValueMap(#__VA_ARGS__); \ + } + + +class JsonHelperPrivate +{ +public: + /****************************************************** + * + * enable_if + * + ******************************************************/ + template + struct enable_if + { + }; + + template + struct enable_if + { + typedef TYPE type; + }; + +public: + /****************************************************** + * + * Check Interface + * If class or struct add AIGC_JSON_HELPER\AIGC_JSON_HELPER_RENAME\AIGC_JSON_HELPER_BASE, + * it will go to the correct conver function. + * + ******************************************************/ + template + struct HasConverFunction + { + template + static char func(decltype(&TT::AIGCJsonToObject)); + + template + static int func(...); + + const static bool has = (sizeof(func(NULL)) == sizeof(char)); + }; + + template + struct HasRenameFunction + { + template + static char func(decltype(&TT::AIGCRenameMembers)); + template + static int func(...); + const static bool has = (sizeof(func(NULL)) == sizeof(char)); + }; + + template + struct HasBaseConverFunction + { + template + static char func(decltype(&TT::AIGCBaseJsonToObject)); + template + static int func(...); + const static bool has = (sizeof(func(NULL)) == sizeof(char)); + }; + + template + struct HasDefaultValueFunction + { + template + static char func(decltype(&TT::AIGCDefaultValues)); + template + static int func(...); + const static bool has = (sizeof(func(NULL)) == sizeof(char)); + }; + +public: + /****************************************************** + * + * Interface of JsonToObject\ObjectToJson + * + ******************************************************/ + template ::has, int>::type = 0> + bool JsonToObject(T &obj, rapidjson::Value &jsonValue) + { + if (!BaseConverJsonToObject(obj, jsonValue)) + return false; + + LoadDefaultValuesMap(obj); + std::vector names = LoadRenameArray(obj); + return obj.AIGCJsonToObject(*this, jsonValue, names); + } + + template ::has, int>::type = 0> + bool JsonToObject(T &obj, rapidjson::Value &jsonValue) + { + if (std::is_enum::value) + { + int ivalue; + if (!JsonToObject(ivalue, jsonValue)) + return false; + + obj = static_cast(ivalue); + return true; + } + + m_message = "unsupported this type."; + return false; + } + + template ::has, int>::type = 0> + bool ObjectToJson(T &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + if (jsonValue.IsNull()) + jsonValue.SetObject(); + if (!BaseConverObjectToJson(obj, jsonValue, allocator)) + return false; + std::vector names = LoadRenameArray(obj); + return obj.AIGCObjectToJson(*this, jsonValue, allocator, names); + } + + template ::has, int>::type = 0> + bool ObjectToJson(T &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + if (std::is_enum::value) + { + int ivalue = static_cast(obj); + return ObjectToJson(ivalue, jsonValue, allocator); + } + + m_message = "unsupported this type."; + return false; + } + + /****************************************************** + * + * Interface of LoadRenameArray + * + ******************************************************/ + template ::has, int>::type = 0> + std::vector LoadRenameArray(T &obj) + { + return obj.AIGCRenameMembers(*this); + } + + template ::has, int>::type = 0> + std::vector LoadRenameArray(T &obj) + { + return std::vector(); + } + + /****************************************************** + * + * Interface of BaseConverJsonToObject\BaseConverObjectToJson + * + ******************************************************/ + template ::has, int>::type = 0> + bool BaseConverJsonToObject(T &obj, rapidjson::Value &jsonValue) + { + return obj.AIGCBaseJsonToObject(*this, jsonValue); + } + + template ::has, int>::type = 0> + bool BaseConverJsonToObject(T &obj, rapidjson::Value &jsonValue) + { + return true; + } + + template ::has, int>::type = 0> + bool BaseConverObjectToJson(T &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + return obj.AIGCBaseObjectToJson(*this, jsonValue, allocator); + } + + template ::has, int>::type = 0> + bool BaseConverObjectToJson(T &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + return true; + } + + /****************************************************** + * + * Interface of Default value + * + ******************************************************/ + template ::has, int>::type = 0> + void LoadDefaultValuesMap(T &obj) + { + obj.AIGCDefaultValues(*this); + } + + template ::has, int>::type = 0> + void LoadDefaultValuesMap(T &obj) + { + (void)obj; + } + +public: + /****************************************************** + * + * Tool function + * + ******************************************************/ + static std::vector StringSplit(const std::string &str, char sep = ',') + { + std::vector array; + std::string::size_type pos1, pos2; + pos1 = 0; + pos2 = str.find(sep); + while (std::string::npos != pos2) + { + array.push_back(str.substr(pos1, pos2 - pos1)); + pos1 = pos2 + 1; + pos2 = str.find(sep, pos1); + } + if (pos1 != str.length()) + array.push_back(str.substr(pos1)); + + return array; + } + + static std::string StringTrim(std::string key) + { + std::string newStr = key; + if (!newStr.empty()) + { + newStr.erase(0, newStr.find_first_not_of(" ")); + newStr.erase(newStr.find_last_not_of(" ") + 1); + } + if (!newStr.empty()) + { + newStr.erase(0, newStr.find_first_not_of("\"")); + newStr.erase(newStr.find_last_not_of("\"") + 1); + } + return newStr; + } + + static void StringTrim(std::vector &array) + { + for (int i = 0; i < (int)array.size(); i++) + { + array[i] = StringTrim(array[i]); + } + } + + /** + * Get json value type + */ + static std::string GetJsonValueTypeName(rapidjson::Value &jsonValue) + { + switch (jsonValue.GetType()) + { + case rapidjson::Type::kArrayType: + return "array"; + case rapidjson::Type::kFalseType: + case rapidjson::Type::kTrueType: + return "bool"; + case rapidjson::Type::kObjectType: + return "object"; + case rapidjson::Type::kStringType: + return "string"; + case rapidjson::Type::kNumberType: + return "number"; + default: + return "string"; + } + } + + static std::string GetStringFromJsonValue(rapidjson::Value &jsonValue) + { + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + + jsonValue.Accept(writer); + std::string ret = std::string(buffer.GetString()); + return ret; + } + + static std::string FindStringFromMap(std::string name, std::map &stringMap) + { + std::map::iterator iter = stringMap.find(name); + if (iter == stringMap.end()) + return ""; + return iter->second; + } + +public: + /****************************************************** + * + * Set class/struct members value + * + ******************************************************/ + std::vector GetMembersNames(const std::string membersStr) + { + std::vector array = StringSplit(membersStr); + StringTrim(array); + return array; + } + + std::map GetMembersValueMap(const std::string valueStr) + { + std::vector array = StringSplit(valueStr); + std::map ret; + for (int i = 0; i < array.size(); i++) + { + std::vector keyValue = StringSplit(array[i], '='); + if (keyValue.size() != 2) + continue; + + std::string key = StringTrim(keyValue[0]); + std::string value = StringTrim(keyValue[1]); + if (ret.find(key) != ret.end()) + continue; + ret.insert(std::pair(key, value)); + } + return ret; + } + + template + bool SetMembers(const std::vector &names, int index, rapidjson::Value &jsonValue, std::map defaultValues, TYPE &arg, TYPES &...args) + { + if (!SetMembers(names, index, jsonValue, defaultValues, arg)) + return false; + + return SetMembers(names, ++index, jsonValue, defaultValues, args...); + } + + template + bool SetMembers(const std::vector &names, int index, rapidjson::Value &jsonValue, std::map defaultValues, TYPE &arg) + { + if (jsonValue.IsNull()) + return true; + + const char *key = names[index].c_str(); + if (!jsonValue.IsObject()) + return false; + if (!jsonValue.HasMember(key)) + { + std::string defaultV = FindStringFromMap(names[index], defaultValues); + if (!defaultV.empty()) + StringToObject(arg, defaultV); + return true; + } + + if (!JsonToObject(arg, jsonValue[key])) + { + m_message = "[" + names[index] + "] " + m_message; + return false; + } + return true; + } + + /****************************************************** + * + * Get class/struct members value + * + ******************************************************/ + template + bool GetMembers(const std::vector &names, int index, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator, TYPE &arg, TYPES &...args) + { + if (!GetMembers(names, index, jsonValue, allocator, arg)) + return false; + return GetMembers(names, ++index, jsonValue, allocator, args...); + } + + template + bool GetMembers(const std::vector &names, int index, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator, TYPE &arg) + { + rapidjson::Value item; + bool check = ObjectToJson(arg, item, allocator); + if (!check) + { + m_message = "[" + names[index] + "] " + m_message; + return false; + } + + if (jsonValue.HasMember(names[index].c_str())) + { + jsonValue.RemoveMember(names[index].c_str()); + } + + rapidjson::Value key; + key.SetString(names[index].c_str(), names[index].length(), allocator); + jsonValue.AddMember(key, item, allocator); + return true; + } + +public: + /****************************************************** + * + * Set base class value + * + ******************************************************/ + template + bool SetBase(rapidjson::Value &jsonValue, TYPE *arg, TYPES *...args) + { + if (!SetBase(jsonValue, arg)) + return false; + return SetBase(jsonValue, args...); + } + + template + bool SetBase(rapidjson::Value &jsonValue, TYPE *arg) + { + return JsonToObject(*arg, jsonValue); + } + + /****************************************************** + * + * Get base class value + * + ******************************************************/ + template + bool GetBase(rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator, TYPE *arg, TYPES *...args) + { + if (!GetBase(jsonValue, allocator, arg)) + return false; + return GetBase(jsonValue, allocator, args...); + } + + template + bool GetBase(rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator, TYPE *arg) + { + return ObjectToJson(*arg, jsonValue, allocator); + } + +public: + /****************************************************** + * Conver base-type : string to base-type + * Contain: int\uint、int64_t\uint64_t、bool、float + * double、string + * + ******************************************************/ + template + void StringToObject(TYPE &obj, std::string &value) + { + return; + } + + void StringToObject(std::string &obj, std::string &value) + { + obj = value; + } + + void StringToObject(int &obj, std::string &value) + { + obj = atoi(value.c_str()); + } + + void StringToObject(unsigned int &obj, std::string &value) + { + char *end; + obj = strtoul(value.c_str(), &end, 10); + } + + void StringToObject(int64_t &obj, std::string &value) + { + char *end; + obj = strtoll(value.c_str(), &end, 10); + } + + void StringToObject(uint64_t &obj, std::string &value) + { + char *end; + obj = strtoull(value.c_str(), &end, 10); + } + + void StringToObject(bool &obj, std::string &value) + { + obj = (value == "true"); + } + + void StringToObject(float &obj, std::string &value) + { + obj = atof(value.c_str()); + } + + void StringToObject(double &obj, std::string &value) + { + obj = atof(value.c_str()); + } + +public: + /****************************************************** + * Conver base-type : Json string to base-type + * Contain: int\uint、int64_t\uint64_t、bool、float + * double、string、vector、list、map + * + ******************************************************/ + bool JsonToObject(int &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsInt()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is int."; + return false; + } + obj = jsonValue.GetInt(); + return true; + } + + bool JsonToObject(unsigned int &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsUint()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is unsigned int."; + return false; + } + obj = jsonValue.GetUint(); + return true; + } + + bool JsonToObject(short &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsInt()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is short."; + return false; + } + obj = jsonValue.GetInt(); + return true; + } + + bool JsonToObject(unsigned short &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsUint()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is unsigned short."; + return false; + } + obj = jsonValue.GetUint(); + return true; + } + + bool JsonToObject(int64_t &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsInt64()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is int64_t."; + return false; + } + obj = jsonValue.GetInt64(); + return true; + } + + bool JsonToObject(uint64_t &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsUint64()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is uint64_t."; + return false; + } + obj = jsonValue.GetUint64(); + return true; + } + + bool JsonToObject(bool &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsBool()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is bool."; + return false; + } + obj = jsonValue.GetBool(); + return true; + } + + bool JsonToObject(float &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsNumber()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is float."; + return false; + } + obj = jsonValue.GetFloat(); + return true; + } + + bool JsonToObject(double &obj, rapidjson::Value &jsonValue) + { + if (!jsonValue.IsNumber()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is double."; + return false; + } + obj = jsonValue.GetDouble(); + return true; + } + + bool JsonToObject(std::string &obj, rapidjson::Value &jsonValue) + { + obj = ""; + if (jsonValue.IsNull()) + return true; + //object or number conver to string + else if (jsonValue.IsObject() || jsonValue.IsNumber()) + obj = GetStringFromJsonValue(jsonValue); + else if (!jsonValue.IsString()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is string."; + return false; + } + else + obj = jsonValue.GetString(); + + return true; + } + + template + bool JsonToObject(std::vector &obj, rapidjson::Value &jsonValue) + { + obj.clear(); + if (!jsonValue.IsArray()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is std::vector."; + return false; + } + + auto array = jsonValue.GetArray(); + for (int i = 0; i < array.Size(); i++) + { + TYPE item; + if (!JsonToObject(item, array[i])) + return false; + obj.push_back(item); + } + return true; + } + + template + bool JsonToObject(std::list &obj, rapidjson::Value &jsonValue) + { + obj.clear(); + if (!jsonValue.IsArray()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is std::list."; + return false; + } + + auto array = jsonValue.GetArray(); + for (int i = 0; i < array.Size(); i++) + { + TYPE item; + if (!JsonToObject(item, array[i])) + return false; + obj.push_back(item); + } + return true; + } + + template + bool JsonToObject(std::map &obj, rapidjson::Value &jsonValue) + { + obj.clear(); + if (!jsonValue.IsObject()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is std::map."; + return false; + } + + for (auto iter = jsonValue.MemberBegin(); iter != jsonValue.MemberEnd(); ++iter) + { + auto key = (iter->name).GetString(); + auto &value = jsonValue[key]; + + TYPE item; + if (!JsonToObject(item, value)) + return false; + + obj.insert(std::pair(key, item)); + } + return true; + } + + template + bool JsonToObject(std::unordered_map &obj, rapidjson::Value &jsonValue) + { + obj.clear(); + if (!jsonValue.IsObject()) + { + m_message = "json-value is " + GetJsonValueTypeName(jsonValue) + " but object is std::unordered_map."; + return false; + } + + for (auto iter = jsonValue.MemberBegin(); iter != jsonValue.MemberEnd(); ++iter) + { + auto key = (iter->name).GetString(); + auto &value = jsonValue[key]; + + TYPE item; + if (!JsonToObject(item, value)) + return false; + + obj.insert(std::pair(key, item)); + } + return true; + } + +public: + /****************************************************** + * Conver base-type : base-type to json string + * Contain: int\uint、int64_t\uint64_t、bool、float + * double、string、vector、list、map + * + ******************************************************/ + bool ObjectToJson(int &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetInt(obj); + return true; + } + + bool ObjectToJson(unsigned int &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetUint(obj); + return true; + } + + bool ObjectToJson(short &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetInt((int)obj); + return true; + } + + bool ObjectToJson(unsigned short &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetUint((unsigned int)obj); + return true; + } + + bool ObjectToJson(int64_t &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetInt64(obj); + return true; + } + + bool ObjectToJson(uint64_t &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetUint64(obj); + return true; + } + + bool ObjectToJson(bool &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetBool(obj); + return true; + } + + bool ObjectToJson(float &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetFloat(obj); + return true; + } + + bool ObjectToJson(double &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetDouble(obj); + return true; + } + + bool ObjectToJson(std::string &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetString(obj.c_str(), obj.length(), allocator); + return true; + } + + template + bool ObjectToJson(std::vector &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + rapidjson::Value array(rapidjson::Type::kArrayType); + for (int i = 0; i < obj.size(); i++) + { + rapidjson::Value item; + if (!ObjectToJson(obj[i], item, allocator)) + return false; + + array.PushBack(item, allocator); + } + + jsonValue = array; + return true; + } + + template + bool ObjectToJson(std::list &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + rapidjson::Value array(rapidjson::Type::kArrayType); + for (auto i = obj.begin(); i != obj.end(); i++) + { + rapidjson::Value item; + if (!ObjectToJson(*i, item, allocator)) + return false; + + array.PushBack(item, allocator); + } + + jsonValue = array; + return true; + } + + template + bool ObjectToJson(std::map &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetObject(); + for (auto iter = obj.begin(); iter != obj.end(); ++iter) + { + auto key = iter->first; + TYPE value = iter->second; + + rapidjson::Value jsonitem; + if (!ObjectToJson(value, jsonitem, allocator)) + return false; + + rapidjson::Value jsonkey; + jsonkey.SetString(key.c_str(), key.length(), allocator); + + jsonValue.AddMember(jsonkey, jsonitem, allocator); + } + return true; + } + + template + bool ObjectToJson(std::unordered_map &obj, rapidjson::Value &jsonValue, rapidjson::Document::AllocatorType &allocator) + { + jsonValue.SetObject(); + for (auto iter = obj.begin(); iter != obj.end(); ++iter) + { + auto key = iter->first; + TYPE value = iter->second; + + rapidjson::Value jsonitem; + if (!ObjectToJson(value, jsonitem, allocator)) + return false; + + rapidjson::Value jsonkey; + jsonkey.SetString(key.c_str(), key.length(), allocator); + + jsonValue.AddMember(jsonkey, jsonitem, allocator); + } + return true; + } + +public: + std::string m_message; +}; + +class JsonHelper +{ +public: + /** + * @brief conver json string to class | struct + * @param obj : class or struct + * @param jsonStr : json string + * @param keys : the path of the object + * @param message : printf err message when conver failed + */ + template + static bool JsonToObject(T &obj, const std::string &jsonStr, const std::vector keys = {}, std::string *message = NULL) + { + //Parse json string + rapidjson::Document root; + root.Parse(jsonStr.c_str()); + if (root.IsNull()) + { + if (message) + *message = "Json string can't parse."; + return false; + } + + //Go to the key-path + std::string path; + rapidjson::Value &value = root; + for (int i = 0; i < (int)keys.size(); i++) + { + const char *find = keys[i].c_str(); + if (!path.empty()) + path += "->"; + path += keys[i]; + + if (!value.IsObject() || !value.HasMember(find)) + { + if (message) + *message = "Can't parse the path [" + path + "]."; + return false; + } + value = value[find]; + } + + //Conver + JsonHelperPrivate handle; + if (!handle.JsonToObject(obj, value)) + { + if (message) + *message = handle.m_message; + return false; + } + return true; + } + + /** + * @brief conver json string to class | struct + * @param jsonStr : json string + * @param defaultT : default value + * @param keys : the path of the object + * @param message : printf err message when conver failed + */ + template + static T Get(const std::string &jsonStr, T defaultT, const std::vector keys = {}, std::string *message = NULL) + { + T obj; + if (JsonToObject(obj, jsonStr, keys, message)) + return obj; + + return defaultT; + } + + /** + * @brief conver class | struct to json string + * @param errMessage : printf err message when conver failed + * @param obj : class or struct + * @param jsonStr : json string + */ + template + static bool ObjectToJson(T &obj, std::string &jsonStr, std::string *message = NULL) + { + rapidjson::Document root; + root.SetObject(); + rapidjson::Document::AllocatorType &allocator = root.GetAllocator(); + + //Conver + JsonHelperPrivate handle; + if (!handle.ObjectToJson(obj, root, allocator)) + { + if (message) + *message = handle.m_message; + return false; + } + + jsonStr = handle.GetStringFromJsonValue(root); + return true; + } +}; + +} // namespace aigc \ No newline at end of file diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj b/NetTunnelSDK/NetTunnelSDK.vcxproj index e2e748c..c00594a 100644 --- a/NetTunnelSDK/NetTunnelSDK.vcxproj +++ b/NetTunnelSDK/NetTunnelSDK.vcxproj @@ -147,6 +147,7 @@ + diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters index bde8c0e..ddc8895 100644 --- a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters +++ b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters @@ -33,6 +33,9 @@ 头文件 + + 头文件 + diff --git a/NetTunnelSDK/globalcfg.h b/NetTunnelSDK/globalcfg.h index b716623..6b0c041 100644 --- a/NetTunnelSDK/globalcfg.h +++ b/NetTunnelSDK/globalcfg.h @@ -11,6 +11,13 @@ typedef struct { BOOL wgExists; ///< wg.exe 是否存在 } WIREGUARD_CFG, *PWIREGUARD_CFG; +typedef struct { + TCHAR wgName[260]; ///< 网卡名称, Windows标识为 UUID + TCHAR wgIpaddr[MAX_IP_LEN]; ///< 网卡 IP 地址 + TCHAR wgNetmask[MAX_IP_LEN]; ///< 网卡子网掩码 + TCHAR wgCfgPath[MAX_PATH]; ///< 配置文件路径 +} WGINTERFACE_CFG, *PWGINTERFACE_CFG; + /** * @brief SDK 全局配置项 */ @@ -22,6 +29,8 @@ typedef struct { spdlog::level::level_enum logLevel; ///< 日志等级 TCHAR cfgPath[MAX_PATH]; ///< 配置文件路径 WIREGUARD_CFG wireguardCfg; ///< wireguard 配置项 @see WIREGUARD_CFG + WGINTERFACE_CFG wgServerCfg; ///< wireguard 服务端网络接口配置 + WGINTERFACE_CFG wgClientCfg; ///< wireguard 客户端网络接口配置 } SDK_CONFIG, *PSDK_CONFIG; #ifdef __cplusplus // If used by C++ code, diff --git a/NetTunnelSDK/misc.cpp b/NetTunnelSDK/misc.cpp index 8c97e7d..03b44f9 100644 --- a/NetTunnelSDK/misc.cpp +++ b/NetTunnelSDK/misc.cpp @@ -33,9 +33,6 @@ int RunCommand(TCHAR *pszCmd, TCHAR *pszResultBuffer, int dwResultBufferSize) { if (pszResultBuffer && dwResultBufferSize > 0) { memset(pszResultBuffer, 0, dwResultBufferSize); - } else { - WinExec(pszCmd, SW_HIDE); - return ERR_SUCCESS; } memset(&si, 0, sizeof(STARTUPINFO)); @@ -64,15 +61,18 @@ int RunCommand(TCHAR *pszCmd, TCHAR *pszResultBuffer, int dwResultBufferSize) { bRet = ::CreateProcess(nullptr, (pszCmd), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi); if (FALSE == bRet) { SPDLOG_ERROR(TEXT("CreateProcess Error")); + return -ERR_CREATE_PROCESS; } // 等待命令执行结束 ::WaitForSingleObject(pi.hThread, INFINITE); ::WaitForSingleObject(pi.hProcess, INFINITE); - // 从匿名管道中读取结果到输出缓冲区 - ::RtlZeroMemory(pszResultBuffer, dwResultBufferSize); - ::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, nullptr, nullptr); + if (pszResultBuffer) { + // 从匿名管道中读取结果到输出缓冲区 + ::RtlZeroMemory(pszResultBuffer, dwResultBufferSize); + ::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, nullptr, nullptr); + } // 关闭句柄, 释放内存 ::CloseHandle(pi.hThread); @@ -83,4 +83,42 @@ int RunCommand(TCHAR *pszCmd, TCHAR *pszResultBuffer, int dwResultBufferSize) { RemoveTailLineBreak(pszResultBuffer, dwResultBufferSize); //pszResultBuffer[dwResultBufferSize - 1] = 0; return ERR_SUCCESS; +} + +void ShowWindowsErrorMessage(const TCHAR *pMsgHead) { + LPVOID buf; + + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_MAX_WIDTH_MASK, + nullptr, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&buf, + 0, + nullptr)) { + SPDLOG_ERROR("{0} Error({1}): {2}", pMsgHead, GetLastError(), buf); + LocalFree(buf); + } else { + SPDLOG_ERROR("{0} Unknown Error{1}.", pMsgHead, GetLastError()); + } +} + +void StringReplaceAll(TCHAR *pOrigin, const TCHAR *pOldStr, const TCHAR *pNewStr) { + using namespace std; + const int maxSize = lstrlen(pOrigin); + string src = string(pOrigin); + for (string::size_type pos(0); pos != string::npos; pos += lstrlen(pNewStr)) { + if ((pos = src.find(pOldStr, pos)) != string::npos) { + src.replace(pos, lstrlen(pOldStr), pNewStr); + } else { + break; + } + } + + memset(pOrigin, 0, maxSize); + StringCbCopyA(pOrigin, maxSize, src.c_str()); +} + +void StringRemoveAll(TCHAR *pOrigin, const TCHAR *pString) { + StringReplaceAll(pOrigin, pString, ""); } \ No newline at end of file diff --git a/NetTunnelSDK/misc.h b/NetTunnelSDK/misc.h index 08937e5..71264ca 100644 --- a/NetTunnelSDK/misc.h +++ b/NetTunnelSDK/misc.h @@ -10,6 +10,23 @@ extern "C" { void RemoveTailLineBreak(TCHAR *pInputStr, int strSize); int RunCommand(TCHAR *pszCmd, TCHAR *pszResultBuffer, int dwResultBufferSize); +/** + * @brief IPv4 子网掩码转 CIDR 掩码 + * @param[in] pNetMask IPv4 子网掩码字符串 + * @return IPv4 CIDR 掩码 + */ +int __cdecl NetmaskToCIDR(const TCHAR *pNetMask); + +/** + * @brief CIDR 掩码转 IPv4 子网掩码 + * @param[in] cidr CIDR 掩码 + * @return CIDR 对应的子网掩码 + */ +const TCHAR *CIDRToNetmask(const UINT8 cidr); + +void ShowWindowsErrorMessage(const TCHAR *pMsgHead); +void StringReplaceAll(TCHAR *pOrigin, const TCHAR *pOldStr, const TCHAR *pNewStr); +void StringRemoveAll(TCHAR *pOrigin, const TCHAR *pString); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/NetTunnelSDK/network.cpp b/NetTunnelSDK/network.cpp index 21765a3..fe9706e 100644 --- a/NetTunnelSDK/network.cpp +++ b/NetTunnelSDK/network.cpp @@ -7,6 +7,7 @@ #include #include "globalcfg.h" +#include "misc.h" #pragma comment(lib, "Iphlpapi.lib") @@ -30,6 +31,243 @@ int NetmaskToCIDR(const TCHAR *pNetMask) { return 0xFF; } +const TCHAR *CIDRToNetmask(const UINT8 cidr) { + const TCHAR *tabCIDR[] = { + TEXT("128.0.0.0"), TEXT("192.0.0.0"), TEXT("224.0.0.0"), TEXT("240.0.0.0"), + TEXT("248.0.0.0"), TEXT("252.0.0.0"), TEXT("254.0.0.0"), TEXT("255.0.0.0"), + TEXT("255.128.0.0"), TEXT("255.192.0.0"), TEXT("255.224.0.0"), TEXT("255.240.0.0"), + TEXT("255.248.0.0"), TEXT("255.252.0.0"), TEXT("255.254.0.0"), TEXT("255.255.0.0"), + TEXT("255.255.128.0"), TEXT("255.255.192.0"), TEXT("255.255.224.0"), TEXT("255.255.240.0"), + TEXT("255.255.248.0"), TEXT("255.255.252.0"), TEXT("255.255.254.0"), TEXT("255.255.255.0"), + TEXT("255.255.255.128"), TEXT("255.255.255.192"), TEXT("255.255.255.224"), TEXT("255.255.255.240"), + TEXT("255.255.255.248"), TEXT("255.255.255.252"), TEXT("255.255.255.254"), TEXT("255.255.255.255")}; + + if (cidr >= 1 && cidr <= std::size(tabCIDR)) { + return tabCIDR[cidr - 1]; + } + + return TEXT(""); +} + +int GetInterfaceIndexByName(const TCHAR *pInterfaceName, int *pIndex) { + int ret; + TCHAR cmdBuf[MAX_PATH]; + TCHAR cmdResult[MAX_PATH] = {}; + const TCHAR *pToken[] = {TEXT("\r\n"), TEXT(" "), TEXT("InterfaceIndex:")}; + + if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) { + SPDLOG_ERROR("Input pInterfaceName params error: {0}", pInterfaceName); + return -ERR_INPUT_PARAMS; + } + + if (pIndex == nullptr) { + SPDLOG_ERROR("Input pIndex params error"); + return -ERR_INPUT_PARAMS; + } + + if (FAILED( + StringCbPrintf(cmdBuf, + MAX_PATH, + "PowerShell -Command \"& {Get-NetAdapter -Name %s | Format-List -Property InterfaceIndex}\"", + pInterfaceName))) { + SPDLOG_ERROR("Format String Error"); + return -ERR_MEMORY_STR; + } + + if ((ret = RunCommand(cmdBuf, cmdResult, MAX_PATH)) != ERR_SUCCESS) { + SPDLOG_ERROR("Run command [{0}] error: {1}", cmdBuf, ret); + return -ERR_CALL_SHELL; + } + + SPDLOG_DEBUG("Run command [{0}] resutl \'{1}\'", cmdBuf, cmdResult); + + // Ƴ + StringRemoveAll(cmdResult, TEXT("\r\n")); + StringRemoveAll(cmdResult, TEXT(" ")); + StringRemoveAll(cmdResult, TEXT("InterfaceIndex:")); + + *pIndex = strtol(cmdResult, nullptr, 10); + + return ERR_SUCCESS; +} + +/** + * @brief ɾӿַ + * @param pInterfaceName + * @return ִн 0: ɹ С0 ʧ @see USER_ERRNO + * - -ERR_INPUT_PARAMS + * - -ERR_MALLOC_MEMORY ڴʧ + * - -ERR_MEMORY_STR ַ + * - -ERR_CALL_SHELL ϵͳʧ + * - ERR_SUCCESS ɹ + */ +int RemoveInterfaceIpAddress(const TCHAR *pInterfaceName) { + int ret; + TCHAR cmdBuf[MAX_PATH]; + + if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) { + SPDLOG_ERROR("Input pInterfaceName params error: {0}", pInterfaceName); + return -ERR_INPUT_PARAMS; + } + + if (FAILED(StringCbPrintf(cmdBuf, + MAX_PATH, + "PowerShell -Command \"& {Remove-NetIPAddress -InterfaceAlias %s -Confirm:$false}\"", + pInterfaceName))) { + SPDLOG_ERROR("Format String Error"); + return -ERR_MEMORY_STR; + } + + if ((ret = RunCommand(cmdBuf, nullptr, 0)) != ERR_SUCCESS) { + SPDLOG_ERROR("Run command [{0}] error: {1}", cmdBuf, ret); + return -ERR_CALL_SHELL; + } + + return ERR_SUCCESS; +} + +int SetInterfaceIpAddress(const TCHAR *pInterfaceName, const TCHAR *pIpaddr, const TCHAR *pNetmask) { + ULONG index = 0; + WCHAR pIfName[] = L"{7D92693A-0F1E-0212-176D-31226AF3E147}"; + if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) { + SPDLOG_ERROR("Input pInterfaceName params error: {0}", pInterfaceName); + return -ERR_INPUT_PARAMS; + } + + if (pIpaddr == nullptr || lstrlen(pIpaddr) == 0) { + SPDLOG_ERROR("Input pIpaddr params error: {0}", pIpaddr); + return -ERR_INPUT_PARAMS; + } + + if (pNetmask == nullptr || lstrlen(pNetmask) == 0) { + SPDLOG_WARN("Input pNetmask params error: {0}", pNetmask); + return -ERR_INPUT_PARAMS; + } + + //MultiByteToWideChar(CP_UTF8, 0, pInterfaceName, lstrlen(pInterfaceName), pIfName, MAX_PATH / sizeof(WCHAR)); + + if (GetAdapterIndex(pIfName, &index) != NO_ERROR) { + ShowWindowsErrorMessage("GetAdapterIndex"); + return -ERR_SYS_CALL; + } + + return ERR_SUCCESS; +} + +int SetInterfaceIpAddressFromCIDR(const TCHAR *pInterfaceName, const TCHAR *pCidrIpaddr) { + TCHAR ipAddr[MAX_IP_LEN]; + TCHAR ip[MAX_IP_LEN]; + TCHAR cidrMask[4]; + const TCHAR *netmask; + TCHAR *token, *p = nullptr; + + if (pInterfaceName == nullptr || lstrlen(pInterfaceName) == 0) { + SPDLOG_ERROR("Input pInterfaceName params error: {0}", pInterfaceName); + return -ERR_INPUT_PARAMS; + } + + if (pCidrIpaddr == nullptr || lstrlen(pCidrIpaddr) == 0) { + SPDLOG_ERROR("Input pCidrIpaddr params error: {0}", pCidrIpaddr); + return -ERR_INPUT_PARAMS; + } + + StringCbCopy(ipAddr, MAX_IP_LEN, pCidrIpaddr); + + // ȡǰIPַ + token = strtok_s(ipAddr, TEXT("/"), &p); + if (token == nullptr) { + SPDLOG_ERROR("CIDR IpAddress string format error: {0}", pCidrIpaddr); + return -ERR_INPUT_PARAMS; + } + StringCbCopy(ip, MAX_IP_LEN, token); + + // ȡ + token = strtok_s(nullptr, TEXT("/"), &p); + if (token == nullptr) { + SPDLOG_ERROR("CIDR IpAddress string format error: {0}", pCidrIpaddr); + return -ERR_INPUT_PARAMS; + } + StringCbCopy(cidrMask, 4, token); + + int cidr = atoi(cidrMask); + netmask = CIDRToNetmask(cidr); + + SPDLOG_DEBUG("CIDR IpAddress convert:{0} --> {1}/{2}", pCidrIpaddr, ip, netmask); + + return SetInterfaceIpAddress(pInterfaceName, ip, netmask); +} + +int GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts) { + PIP_ADAPTER_INFO pAdapterInfo; + DWORD dwRetVal = 0; + + if (pItemCounts == nullptr || pInfo == nullptr) { + SPDLOG_ERROR("Input params error: {0}"); + return -ERR_INPUT_PARAMS; + } + + ULONG ulOutBufLen = sizeof(IP_ADAPTER_INFO); + pAdapterInfo = static_cast(HeapAlloc(GetProcessHeap(), 0, sizeof(IP_ADAPTER_INFO))); + + if (pAdapterInfo == nullptr) { + SPDLOG_ERROR("Error allocating memory needed to call GetAdaptersinfo"); + return -ERR_MALLOC_MEMORY; + } + + if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW) { + HeapFree(GetProcessHeap(), 0, pAdapterInfo); + pAdapterInfo = static_cast(HeapAlloc(GetProcessHeap(), 0, ulOutBufLen)); + if (pAdapterInfo == nullptr) { + SPDLOG_ERROR("Error allocating memory needed to call GetAdaptersinfo\n"); + return -ERR_MALLOC_MEMORY; + } + } + + if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR) { + UINT32 id = 0; + PIP_ADAPTER_INFO pAdapter = pAdapterInfo; + while (pAdapter && id < NET_CARD_MAX) { + // + pInfo[id].InterfaceIndex = pAdapter->Index; + // + StringCbCopy(pInfo[id].NetCardUUID, MAX_ADAPTER_NAME_LENGTH, pAdapter->AdapterName); + // ϸ + StringCbCopy(pInfo[id].NetCardDescription, MAX_ADAPTER_DESCRIPTION_LENGTH, pAdapter->Description); + // IP ַ + StringCbCopy(pInfo[id].NetCardIpaddr, MAX_IP_LEN - 1, pAdapter->IpAddressList.IpAddress.String); + // + StringCbCopy(pInfo[id].NetCardNetmask, MAX_IP_LEN - 1, pAdapter->IpAddressList.IpMask.String); + // صַ + StringCbCopy(pInfo[id].NetCardGateway, MAX_IP_LEN - 1, pAdapter->GatewayList.IpAddress.String); + // MAC ַ + StringCbPrintf(pInfo[id].NetCardMacAddr, + 20 - 1, + "%02X:%02X:%02X:%02X:%02X:%02X", + pAdapter->Address[0], + pAdapter->Address[1], + pAdapter->Address[2], + pAdapter->Address[3], + pAdapter->Address[4], + pAdapter->Address[5]); + + id++; + pAdapter = pAdapter->Next; + } + + *pItemCounts = id; + } else { + SPDLOG_ERROR("GetAdaptersInfo failed with error: {0}\n", dwRetVal); + return -ERR_SYS_CALL; + } + + if (pAdapterInfo) { + HeapFree(GetProcessHeap(), 0, pAdapterInfo); + } + + return ERR_SUCCESS; +} + +#if 0 int GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts) { int nRel, id = 0; IP_ADDR_STRING *pIpAddrString; @@ -54,14 +292,15 @@ int GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts) { PIP_ADAPTER_INFO cur = pIpAdapterInfo; while (cur) { - StringCbCopy(pInfo[id].NetCardName, MAX_ADAPTER_NAME_LENGTH, cur->AdapterName); + pInfo[id].InterfaceIndex = cur->Index; + StringCbCopy(pInfo[id].NetCardUUID, MAX_ADAPTER_NAME_LENGTH, cur->AdapterName); StringCbCopy(pInfo[id].NetCardDescription, MAX_ADAPTER_DESCRIPTION_LENGTH, cur->Description); switch (cur->Type) { case MIB_IF_TYPE_ETHERNET: pIpAddrString = &(cur->IpAddressList); - StringCbCopy(pInfo[id].NetCardIpaddr, 20 - 1, pIpAddrString->IpAddress.String); - StringCbCopy(pInfo[id].NetCardNetmask, 20 - 1, pIpAddrString->IpMask.String); + StringCbCopy(pInfo[id].NetCardIpaddr, MAX_IP_LEN - 1, pIpAddrString->IpAddress.String); + StringCbCopy(pInfo[id].NetCardNetmask, MAX_IP_LEN - 1, pIpAddrString->IpMask.String); break; case MIB_IF_TYPE_OTHER: case MIB_IF_TYPE_TOKENRING: @@ -72,8 +311,8 @@ int GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts) { break; default: // WIFI ,Unknown type pIpAddrString = &(cur->IpAddressList); - StringCbCopy(pInfo[id].NetCardIpaddr, 20 - 1, pIpAddrString->IpAddress.String); - StringCbCopy(pInfo[id].NetCardNetmask, 20 - 1, pIpAddrString->IpMask.String); + StringCbCopy(pInfo[id].NetCardIpaddr, MAX_IP_LEN - 1, pIpAddrString->IpAddress.String); + StringCbCopy(pInfo[id].NetCardNetmask, MAX_IP_LEN - 1, pIpAddrString->IpMask.String); break; } @@ -96,4 +335,5 @@ int GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts) { delete[] pIpAdapterInfo; return ERR_SUCCESS; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/NetTunnelSDK/tunnel.h b/NetTunnelSDK/tunnel.h index 95818fb..21a4264 100644 --- a/NetTunnelSDK/tunnel.h +++ b/NetTunnelSDK/tunnel.h @@ -18,6 +18,11 @@ constexpr auto WG_KEY_MAX = (64); */ #define NET_CARD_MAX (32) +/** + * @brief IP 字符串最大长度(支持IPv6) + */ +#define MAX_IP_LEN (48) + /** * @brief 协议加密类型 * @@ -50,11 +55,13 @@ enum LOG_LEVEL { * @brief 本地计算机网卡信息 */ typedef struct { - TCHAR NetCardName[260]; ///< 网卡名称, Windows标识为 UUID - TCHAR NetCardDescription[132]; ///< 网卡描述 - TCHAR NetCardIpaddr[20]; ///< 网卡 IP 地址 - TCHAR NetCardNetmask[20]; ///< 网卡子网掩码 - TCHAR NetCardMacAddr[20]; ///< 网卡 MAC 地址 + int InterfaceIndex; ///< 网卡索引 + TCHAR NetCardUUID[260]; ///< 网卡名称, Windows标识为 UUID + TCHAR NetCardDescription[132]; ///< 网卡描述 + TCHAR NetCardIpaddr[MAX_IP_LEN]; ///< 网卡 IP 地址 + TCHAR NetCardNetmask[MAX_IP_LEN]; ///< 网卡子网掩码 + TCHAR NetCardGateway[MAX_IP_LEN]; ///< 网卡网关 + TCHAR NetCardMacAddr[20]; ///< 网卡 MAC 地址 } NIC_CONTENT, *PNIC_CONTENT; /** @@ -206,11 +213,31 @@ TUNNEL_API void __cdecl TunnelSDKUnInit(); TUNNEL_API int __cdecl GetAllNICInfo(PNIC_CONTENT pInfo, int *pItemCounts); /** - * @brief IPv4 子网掩码转 CIDR 掩码 - * @param pNetMask IPv4 子网掩码字符串 - * @return IPv4 CIDR 掩码 + * @brief 获取网卡接口索引编号 + * @param pInterfaceName 网卡名称 + * @param pIndex 网卡索引 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_MALLOC_MEMORY 分配内存失败 + * - -ERR_MEMORY_STR 字符串处理 + * - -ERR_CALL_SHELL 调用系统命令行失败 + * - ERR_SUCCESS 成功 */ -TUNNEL_API int __cdecl NetmaskToCIDR(const TCHAR *pNetMask); +TUNNEL_API int __cdecl GetInterfaceIndexByName(const TCHAR *pInterfaceName, int *pIndex); + +/** + * @brief 删除接口网络地址 + * @param pInterfaceName 网卡名称 + * @return 函数执行结果 0: 成功, 小于0 失败 @see USER_ERRNO + * - -ERR_INPUT_PARAMS 输入参数错误 + * - -ERR_MALLOC_MEMORY 分配内存失败 + * - -ERR_MEMORY_STR 字符串处理 + * - -ERR_CALL_SHELL 调用系统命令行失败 + * - ERR_SUCCESS 成功 + */ +TUNNEL_API int __cdecl RemoveInterfaceIpAddress(const TCHAR *pInterfaceName); + +TUNNEL_API int __cdecl SetInterfaceIpAddressFromCIDR(const TCHAR *pInterfaceName, const TCHAR *pCidrIpaddr); #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/NetTunnelSDK/usrerr.h b/NetTunnelSDK/usrerr.h index 75a5b97..4ffaaa6 100644 --- a/NetTunnelSDK/usrerr.h +++ b/NetTunnelSDK/usrerr.h @@ -1,24 +1,26 @@ #pragma once + /** * @brief SDK 常用错误码 */ enum USER_ERRNO { - ERR_SUCCESS, ///< 成功 - ERR_INPUT_PARAMS, ///< 输入参数错误 - ERR_UN_SUPPORT, ///< 不支持的操作 - ERR_CALL_SHELL, ///< 调用Shell命令失败 - ERR_ITEM_EXISTS, ///< 该内容已经存在 - ERR_ITEM_UNEXISTS, ///< 该内容不存在 - ERR_SYS_INIT, ///< 系统中断 - ERR_SYS_CALL, ///< 系统调用 - ERR_OPEN_FILE, ///< 打开文件失败 - ERR_READ_FILE, ///< 读取文件失败 - ERR_WRITE_FILE, ///< 写入文件失败 - ERR_FILE_NOT_EXISTS, ///< 文件不存在 - ERR_FILE_LOCKED, ///< 文件被锁定 - ERR_GET_FILE_SIZE, ///< 获取文件大小失败 - ERR_COPY_FILE, ///< 复制文件失败 - ERR_MALLOC_MEMORY, ///< 分配内存失败 - ERR_MMAP_MEMORY, ///< 共享内存失败 - ERR_MEMORY_STR ///< 字符串操作失败 + ERR_SUCCESS, ///< 成功 + ERR_INPUT_PARAMS, ///< 输入参数错误 + ERR_UN_SUPPORT, ///< 不支持的操作 + ERR_CALL_SHELL, ///< 调用Shell命令失败 + ERR_ITEM_EXISTS, ///< 该内容已经存在 + ERR_ITEM_UNEXISTS, ///< 该内容不存在 + ERR_SYS_INIT, ///< 系统中断 + ERR_SYS_CALL, ///< 系统调用 + ERR_OPEN_FILE, ///< 打开文件失败 + ERR_READ_FILE, ///< 读取文件失败 + ERR_WRITE_FILE, ///< 写入文件失败 + ERR_FILE_NOT_EXISTS, ///< 文件不存在 + ERR_FILE_LOCKED, ///< 文件被锁定 + ERR_GET_FILE_SIZE, ///< 获取文件大小失败 + ERR_COPY_FILE, ///< 复制文件失败 + ERR_MALLOC_MEMORY, ///< 分配内存失败 + ERR_MMAP_MEMORY, ///< 共享内存失败 + ERR_MEMORY_STR, ///< 字符串操作失败 + ERR_CREATE_PROCESS ///< 创建进程失败 }; \ No newline at end of file diff --git a/NetTunnelSDK/wireguard.cpp b/NetTunnelSDK/wireguard.cpp index 8d3e451..f0357a6 100644 --- a/NetTunnelSDK/wireguard.cpp +++ b/NetTunnelSDK/wireguard.cpp @@ -14,8 +14,7 @@ constexpr auto WINENVBUF_SIZE = (4096); #define CFG_WIREGUARD_SECTION TEXT("WireGuard") #define CFG_WIREGUARD_PATH TEXT("WireGuardExe") -#define CFG_WGCLI_PATH TEXT("ClientConfig") -#define CFG_WGSVR_PATH TEXT("ServerConfig") +#define CFG_WGCFG_PATH TEXT("WgCfgPath") #define CFG_WG_PATH TEXT("WgExe") int WireGuardInstallServerService(bool bInstall) { @@ -23,7 +22,7 @@ int WireGuardInstallServerService(bool bInstall) { TCHAR cmdBuf[MAX_PATH]; GetPrivateProfileString(CFG_WIREGUARD_SECTION, - CFG_WGSVR_PATH, + CFG_WGCFG_PATH, TEXT(""), cfgVal, MAX_PATH, @@ -71,7 +70,7 @@ int WireGuardInstallServerService(bool bInstall) { return -ERR_FILE_NOT_EXISTS; } } else { - SPDLOG_ERROR("Configure [{0}] not found", CFG_WGSVR_PATH); + SPDLOG_ERROR("Configure [{0}] not found", CFG_WGCFG_PATH); return -ERR_ITEM_UNEXISTS; } } @@ -148,7 +147,7 @@ int WireGuardCreateClientConfig(const PWGCLIENT_CONFIG pWgConfig) { } // 保存到配置文件中 - WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WGCLI_PATH, cfgPath, GetGlobalCfgInfo()->cfgPath); + WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WGCFG_PATH, cfgPath, GetGlobalCfgInfo()->cfgPath); if (FAILED(StringCbPrintf(pBuf, bufSize, @@ -258,7 +257,7 @@ int WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgConfig) { return -ERR_OPEN_FILE; } - WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WGSVR_PATH, cfgPath, GetGlobalCfgInfo()->cfgPath); + WritePrivateProfileString(CFG_WIREGUARD_SECTION, CFG_WGCFG_PATH, cfgPath, GetGlobalCfgInfo()->cfgPath); if (FAILED(StringCbPrintf(pBuf, bufSize, @@ -297,6 +296,9 @@ int WireGuardCreateServerConfig(const PWGSERVER_CONFIG pWgConfig) { } ::CloseHandle(hFile); + + StringCbCopy(GetGlobalCfgInfo()->wgServerCfg.wgName, 260, pWgConfig->Name); + StringCbCopy(GetGlobalCfgInfo()->wgServerCfg.wgIpaddr, MAX_IP_LEN, pWgConfig->Address); return ERR_SUCCESS; } diff --git a/TestNetTunnelSDK/TestNetTunnelSDK.cpp b/TestNetTunnelSDK/TestNetTunnelSDK.cpp index fc90b73..77ed46d 100644 --- a/TestNetTunnelSDK/TestNetTunnelSDK.cpp +++ b/TestNetTunnelSDK/TestNetTunnelSDK.cpp @@ -6,42 +6,34 @@ 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); +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: + const int RET_OK = ERR_SUCCESS; + + TEST_METHOD(TestFindWireguardExe) { + Assert::AreEqual(RET_OK, FindWireguardExe(nullptr, 0)); } - TEST_MODULE_CLEANUP(ModuleCleanup) - { - Logger::WriteMessage("In Module Cleanup"); - TunnelSDKUnInit(); + TEST_METHOD(TestSetWireguardPath) { + Assert::AreEqual(RET_OK, SetWireguardPath(TEXT("C:\\Program Files\\WireGuard\\wireguard.exe"))); } - 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) - { + TEST_METHOD(TestRunPipeCmd) { #if 0 TCHAR buf[1024]; int ret = ERR_SUCCESS; @@ -50,18 +42,32 @@ namespace TestNetTunnelSDK 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)); + TEST_METHOD(TestGetAllNICInfo) { + PNIC_CONTENT pInfo = (PNIC_CONTENT)malloc(sizeof(NIC_CONTENT) * 32); - free(pInfo); - } - }; -} + int size = 0; + + Assert::AreEqual(RET_OK, GetAllNICInfo(pInfo, &size)); + + free(pInfo); + } + + TEST_METHOD(TestSetInterfaceIpAddressFromCIDR) { + Assert::AreEqual( + RET_OK, + SetInterfaceIpAddressFromCIDR(TEXT("{7D92693A-0F1E-0212-176D-31226AF3E147}"), TEXT("192.168.100.250/24"))); + } + + TEST_METHOD(TestGetInterfaceIndexByName) { + int index; + Assert::AreEqual(RET_OK, GetInterfaceIndexByName(TEXT("wg_server"), &index)); + } + + TEST_METHOD(TestRemoveInterfaceIpAddress) { + int index; + Assert::AreEqual(RET_OK, RemoveInterfaceIpAddress(TEXT("wg_server"))); + } +}; +} \ No newline at end of file diff --git a/tunnel_windows.sln.DotSettings.user b/tunnel_windows.sln.DotSettings.user index d742a04..65fbad0 100644 --- a/tunnel_windows.sln.DotSettings.user +++ b/tunnel_windows.sln.DotSettings.user @@ -1,3 +1,3 @@  SOLUTION - ShowAndRun \ No newline at end of file + \ No newline at end of file