diff --git a/.gitignore b/.gitignore
index ad4d030..077294b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,11 +3,10 @@
################################################################################
/.vs
-/NetTunnelApp/bin
-/NetTunnelApp/obj/
-/NetTunnelSDK/x64/
+bin/
+obj/
+x64/
/x64/
-/TestNetTunnelSDK/x64/Debug
+Debug/
/packages/System.Buffers.4.5.1
-/Installer/Debug
-/InstallTunnelSDK/Debug
+/packages/DllExport.1.6.4
diff --git a/InstallTunnelSDK/InstallTunnelSDK.vdproj b/InstallTunnelSDK/InstallTunnelSDK.vdproj
index 040ab4c..947da65 100644
--- a/InstallTunnelSDK/InstallTunnelSDK.vdproj
+++ b/InstallTunnelSDK/InstallTunnelSDK.vdproj
@@ -99,6 +99,12 @@
}
"Entry"
{
+ "MsmKey" = "8:_6A1A279D341B4A5D87C6D56C726E2979"
+ "OwnerKey" = "8:_UNDEFINED"
+ "MsmSig" = "8:_UNDEFINED"
+ }
+ "Entry"
+ {
"MsmKey" = "8:_6A8B2CA20D527217332BB0170E559DB9"
"OwnerKey" = "8:_00EB5BF3E5624995855CCF580A8AD1D5"
"MsmSig" = "8:_UNDEFINED"
@@ -184,12 +190,6 @@
"Entry"
{
"MsmKey" = "8:_UNDEFINED"
- "OwnerKey" = "8:_513E5CF8D0F56603CEA37562D0DCB474"
- "MsmSig" = "8:_UNDEFINED"
- }
- "Entry"
- {
- "MsmKey" = "8:_UNDEFINED"
"OwnerKey" = "8:_10E071CF096B417C925C5E27E36CE39A"
"MsmSig" = "8:_UNDEFINED"
}
@@ -223,6 +223,12 @@
"OwnerKey" = "8:_061110FCF275ABD7AB2CF878EE47397D"
"MsmSig" = "8:_UNDEFINED"
}
+ "Entry"
+ {
+ "MsmKey" = "8:_UNDEFINED"
+ "OwnerKey" = "8:_513E5CF8D0F56603CEA37562D0DCB474"
+ "MsmSig" = "8:_UNDEFINED"
+ }
}
"Configurations"
{
@@ -241,6 +247,22 @@
"PrivateKeyFile" = "8:"
"TimeStampServer" = "8:"
"InstallerBootstrapper" = "3:2"
+ "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
+ {
+ "Enabled" = "11:TRUE"
+ "PromptEnabled" = "11:TRUE"
+ "PrerequisitesLocation" = "2:1"
+ "Url" = "8:"
+ "ComponentsUrl" = "8:"
+ "Items"
+ {
+ "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
+ {
+ "Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
+ "ProductCode" = "8:.NETFramework,Version=v4.7.2"
+ }
+ }
+ }
}
"Release"
{
@@ -257,6 +279,14 @@
"PrivateKeyFile" = "8:"
"TimeStampServer" = "8:"
"InstallerBootstrapper" = "3:2"
+ "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
+ {
+ "Enabled" = "11:TRUE"
+ "PromptEnabled" = "11:TRUE"
+ "PrerequisitesLocation" = "2:1"
+ "Url" = "8:"
+ "ComponentsUrl" = "8:"
+ }
}
}
"Deployable"
@@ -459,6 +489,26 @@
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
+ "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6A1A279D341B4A5D87C6D56C726E2979"
+ {
+ "SourcePath" = "8:..\\NetTunnelSDK\\resource\\iconsTray.ico"
+ "TargetName" = "8:iconsTray.ico"
+ "Tag" = "8:"
+ "Folder" = "8:_A69AEF7ED77C4BB28FA87F3D7B5FF39A"
+ "Condition" = "8:"
+ "Transitive" = "11:FALSE"
+ "Vital" = "11:TRUE"
+ "ReadOnly" = "11:FALSE"
+ "Hidden" = "11:FALSE"
+ "System" = "11:FALSE"
+ "Permanent" = "11:FALSE"
+ "SharedLegacy" = "11:FALSE"
+ "PackageAs" = "3:1"
+ "Register" = "3:1"
+ "Exclude" = "11:FALSE"
+ "IsDependency" = "11:FALSE"
+ "IsolateTo" = "8:"
+ }
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6A8B2CA20D527217332BB0170E559DB9"
{
"SourcePath" = "8:ucrtbased.dll"
@@ -515,7 +565,7 @@
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
- "Exclude" = "11:FALSE"
+ "Exclude" = "11:TRUE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
@@ -535,7 +585,7 @@
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
- "Exclude" = "11:FALSE"
+ "Exclude" = "11:TRUE"
"IsDependency" = "11:TRUE"
"IsolateTo" = "8:"
}
@@ -689,7 +739,7 @@
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:SCC"
"ProductCode" = "8:{FC04A2D1-FDD4-485A-88CC-67543D0B07FC}"
- "PackageCode" = "8:{18F34BAE-0E72-485B-A6EB-9A62761CD03B}"
+ "PackageCode" = "8:{E72A3533-046D-464B-A2A8-C1326AC51F4F}"
"UpgradeCode" = "8:{E4E3F1C5-78D9-4F56-AA5F-2C68C839E21E}"
"AspNetVersion" = "8:"
"RestartWWWService" = "11:FALSE"
@@ -706,7 +756,7 @@
"Keywords" = "8:"
"ARPCOMMENTS" = "8:"
"ARPURLINFOABOUT" = "8:"
- "ARPPRODUCTICON" = "8:"
+ "ARPPRODUCTICON" = "8:_6A1A279D341B4A5D87C6D56C726E2979"
"ARPIconIndex" = "3:0"
"SearchPath" = "8:"
"UseSystemSearchPath" = "11:TRUE"
diff --git a/NetTunnelApp/MainForm.Designer.cs b/NetTunnelApp/MainForm.Designer.cs
index 2d91858..279b0bb 100644
--- a/NetTunnelApp/MainForm.Designer.cs
+++ b/NetTunnelApp/MainForm.Designer.cs
@@ -50,15 +50,18 @@
this.menuControlHeartStart = new System.Windows.Forms.ToolStripMenuItem();
this.menuControlHeartStop = new System.Windows.Forms.ToolStripMenuItem();
this.menuMainSet = new System.Windows.Forms.ToolStripMenuItem();
- this.menuSetModeShareNet = new System.Windows.Forms.ToolStripMenuItem();
- this.menuSetModeShareServer = new System.Windows.Forms.ToolStripMenuItem();
this.menuSetMode = new System.Windows.Forms.ToolStripMenuItem();
this.menuSetModeClient = new System.Windows.Forms.ToolStripMenuItem();
this.menuSetModeServer = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuSetModeShareNet = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuSetModeShareServer = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this.menuSetVPN = new System.Windows.Forms.ToolStripMenuItem();
this.menuSetVPNPath = new System.Windows.Forms.ToolStripMenuItem();
this.menuSetExitToTray = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuSetShareMode = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuSetShareModeICS = new System.Windows.Forms.ToolStripMenuItem();
+ this.menuSetShareModeNAT = new System.Windows.Forms.ToolStripMenuItem();
this.menuMainHelp = new System.Windows.Forms.ToolStripMenuItem();
this.statusMain = new System.Windows.Forms.StatusStrip();
this.tbMain = new System.Windows.Forms.ToolStrip();
@@ -71,9 +74,6 @@
this.trapMenuSysInterface = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
this.trapMenuExit = new System.Windows.Forms.ToolStripMenuItem();
- this.menuControlNetMode = new System.Windows.Forms.ToolStripMenuItem();
- this.menuControlNetModePrivate = new System.Windows.Forms.ToolStripMenuItem();
- this.menuControlNetModePublic = new System.Windows.Forms.ToolStripMenuItem();
this.menuMain.SuspendLayout();
this.trapMenuMain.SuspendLayout();
this.SuspendLayout();
@@ -157,8 +157,7 @@
this.menuControlSetCliParams,
this.toolStripSeparator2,
this.menuControlService,
- this.menuControlHeart,
- this.menuControlNetMode});
+ this.menuControlHeart});
this.menuControl.Name = "menuControl";
this.menuControl.Size = new System.Drawing.Size(60, 21);
this.menuControl.Text = "操作(&C)";
@@ -166,27 +165,27 @@
// menuControlRefInterface
//
this.menuControlRefInterface.Name = "menuControlRefInterface";
- this.menuControlRefInterface.Size = new System.Drawing.Size(192, 22);
+ this.menuControlRefInterface.Size = new System.Drawing.Size(180, 22);
this.menuControlRefInterface.Text = "获取网络接口(&I)";
this.menuControlRefInterface.Click += new System.EventHandler(this.menuControlRefInterface_Click);
//
// menuControlEnv
//
this.menuControlEnv.Name = "menuControlEnv";
- this.menuControlEnv.Size = new System.Drawing.Size(192, 22);
+ this.menuControlEnv.Size = new System.Drawing.Size(180, 22);
this.menuControlEnv.Text = "运行环境检测(&T)";
//
// menuControlSetCliParams
//
this.menuControlSetCliParams.Name = "menuControlSetCliParams";
- this.menuControlSetCliParams.Size = new System.Drawing.Size(192, 22);
+ this.menuControlSetCliParams.Size = new System.Drawing.Size(180, 22);
this.menuControlSetCliParams.Text = "设置隧道参数(&N)";
this.menuControlSetCliParams.Click += new System.EventHandler(this.menuControlSetCliParams_Click);
//
// toolStripSeparator2
//
this.toolStripSeparator2.Name = "toolStripSeparator2";
- this.toolStripSeparator2.Size = new System.Drawing.Size(189, 6);
+ this.toolStripSeparator2.Size = new System.Drawing.Size(177, 6);
//
// menuControlService
//
@@ -194,7 +193,7 @@
this.menuControlSvrStart,
this.menuControlSvrStop});
this.menuControlService.Name = "menuControlService";
- this.menuControlService.Size = new System.Drawing.Size(192, 22);
+ this.menuControlService.Size = new System.Drawing.Size(180, 22);
this.menuControlService.Text = "隧道服务管理(&V)";
//
// menuControlSvrStart
@@ -217,20 +216,20 @@
this.menuControlHeartStart,
this.menuControlHeartStop});
this.menuControlHeart.Name = "menuControlHeart";
- this.menuControlHeart.Size = new System.Drawing.Size(192, 22);
+ this.menuControlHeart.Size = new System.Drawing.Size(180, 22);
this.menuControlHeart.Text = "心跳服务管理(&H)";
//
// menuControlHeartStart
//
this.menuControlHeartStart.Name = "menuControlHeartStart";
- this.menuControlHeartStart.Size = new System.Drawing.Size(180, 22);
+ this.menuControlHeartStart.Size = new System.Drawing.Size(148, 22);
this.menuControlHeartStart.Text = "启动心跳服务";
this.menuControlHeartStart.Click += new System.EventHandler(this.menuControlHeartStart_Click);
//
// menuControlHeartStop
//
this.menuControlHeartStop.Name = "menuControlHeartStop";
- this.menuControlHeartStop.Size = new System.Drawing.Size(180, 22);
+ this.menuControlHeartStop.Size = new System.Drawing.Size(148, 22);
this.menuControlHeartStop.Text = "停止心跳服务";
this.menuControlHeartStop.Click += new System.EventHandler(this.menuControlHeartStop_Click);
//
@@ -242,23 +241,12 @@
this.menuSetModeShareServer,
this.toolStripSeparator1,
this.menuSetVPN,
- this.menuSetExitToTray});
+ this.menuSetExitToTray,
+ this.menuSetShareMode});
this.menuMainSet.Name = "menuMainSet";
this.menuMainSet.Size = new System.Drawing.Size(59, 21);
this.menuMainSet.Text = "设置(&S)";
//
- // menuSetModeShareNet
- //
- this.menuSetModeShareNet.Name = "menuSetModeShareNet";
- this.menuSetModeShareNet.Size = new System.Drawing.Size(180, 22);
- this.menuSetModeShareNet.Text = "共享网络";
- //
- // menuSetModeShareServer
- //
- this.menuSetModeShareServer.Name = "menuSetModeShareServer";
- this.menuSetModeShareServer.Size = new System.Drawing.Size(180, 22);
- this.menuSetModeShareServer.Text = "云电脑服务器";
- //
// menuSetMode
//
this.menuSetMode.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
@@ -284,6 +272,18 @@
this.menuSetModeServer.Text = "服务端";
this.menuSetModeServer.Click += new System.EventHandler(this.menuSetModeServer_Click);
//
+ // menuSetModeShareNet
+ //
+ this.menuSetModeShareNet.Name = "menuSetModeShareNet";
+ this.menuSetModeShareNet.Size = new System.Drawing.Size(180, 22);
+ this.menuSetModeShareNet.Text = "共享网络";
+ //
+ // menuSetModeShareServer
+ //
+ this.menuSetModeShareServer.Name = "menuSetModeShareServer";
+ this.menuSetModeShareServer.Size = new System.Drawing.Size(180, 22);
+ this.menuSetModeShareServer.Text = "云电脑服务器";
+ //
// toolStripSeparator1
//
this.toolStripSeparator1.Name = "toolStripSeparator1";
@@ -300,7 +300,7 @@
// menuSetVPNPath
//
this.menuSetVPNPath.Name = "menuSetVPNPath";
- this.menuSetVPNPath.Size = new System.Drawing.Size(180, 22);
+ this.menuSetVPNPath.Size = new System.Drawing.Size(124, 22);
this.menuSetVPNPath.Text = "安装路径";
this.menuSetVPNPath.Click += new System.EventHandler(this.menuSetVPNPath_Click);
//
@@ -312,6 +312,31 @@
this.menuSetExitToTray.Size = new System.Drawing.Size(180, 22);
this.menuSetExitToTray.Text = "退出时最小化(&M)";
//
+ // menuSetShareMode
+ //
+ this.menuSetShareMode.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.menuSetShareModeICS,
+ this.menuSetShareModeNAT});
+ this.menuSetShareMode.Name = "menuSetShareMode";
+ this.menuSetShareMode.Size = new System.Drawing.Size(180, 22);
+ this.menuSetShareMode.Text = "网络共享模式";
+ //
+ // menuSetShareModeICS
+ //
+ this.menuSetShareModeICS.Checked = true;
+ this.menuSetShareModeICS.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.menuSetShareModeICS.Name = "menuSetShareModeICS";
+ this.menuSetShareModeICS.Size = new System.Drawing.Size(194, 22);
+ this.menuSetShareModeICS.Text = "Intelnet连接共享(ICS)";
+ this.menuSetShareModeICS.Click += new System.EventHandler(this.menuSetShareModeICS_Click);
+ //
+ // menuSetShareModeNAT
+ //
+ this.menuSetShareModeNAT.Name = "menuSetShareModeNAT";
+ this.menuSetShareModeNAT.Size = new System.Drawing.Size(194, 22);
+ this.menuSetShareModeNAT.Text = "网络地址转换(NAT)";
+ this.menuSetShareModeNAT.Click += new System.EventHandler(this.menuSetShareModeNAT_Click);
+ //
// menuMainHelp
//
this.menuMainHelp.Name = "menuMainHelp";
@@ -358,67 +383,46 @@
this.toolStripSeparator3,
this.trapMenuExit});
this.trapMenuMain.Name = "trapMenuMain";
- this.trapMenuMain.Size = new System.Drawing.Size(181, 126);
+ this.trapMenuMain.Size = new System.Drawing.Size(137, 104);
this.trapMenuMain.UseWaitCursor = true;
//
// trapMenuShowMainWnd
//
this.trapMenuShowMainWnd.Name = "trapMenuShowMainWnd";
- this.trapMenuShowMainWnd.Size = new System.Drawing.Size(180, 22);
+ this.trapMenuShowMainWnd.Size = new System.Drawing.Size(136, 22);
this.trapMenuShowMainWnd.Text = "显示主界面";
this.trapMenuShowMainWnd.Click += new System.EventHandler(this.trapMenuShowMainWnd_Click);
//
// trapMenuHideMain
//
this.trapMenuHideMain.Name = "trapMenuHideMain";
- this.trapMenuHideMain.Size = new System.Drawing.Size(180, 22);
+ this.trapMenuHideMain.Size = new System.Drawing.Size(136, 22);
this.trapMenuHideMain.Text = "隐藏主界面";
this.trapMenuHideMain.Click += new System.EventHandler(this.trapMenuHideMain_Click);
//
// toolStripSeparator5
//
this.toolStripSeparator5.Name = "toolStripSeparator5";
- this.toolStripSeparator5.Size = new System.Drawing.Size(177, 6);
+ this.toolStripSeparator5.Size = new System.Drawing.Size(133, 6);
//
// trapMenuSysInterface
//
this.trapMenuSysInterface.Name = "trapMenuSysInterface";
- this.trapMenuSysInterface.Size = new System.Drawing.Size(180, 22);
+ this.trapMenuSysInterface.Size = new System.Drawing.Size(136, 22);
this.trapMenuSysInterface.Text = "共享网络";
//
// toolStripSeparator3
//
this.toolStripSeparator3.Name = "toolStripSeparator3";
- this.toolStripSeparator3.Size = new System.Drawing.Size(177, 6);
+ this.toolStripSeparator3.Size = new System.Drawing.Size(133, 6);
//
// trapMenuExit
//
this.trapMenuExit.Name = "trapMenuExit";
- this.trapMenuExit.Size = new System.Drawing.Size(180, 22);
+ this.trapMenuExit.Size = new System.Drawing.Size(136, 22);
this.trapMenuExit.Text = "退出程序";
this.trapMenuExit.Click += new System.EventHandler(this.trapMenuExit_Click);
//
- // menuControlNetMode
- //
- this.menuControlNetMode.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
- this.menuControlNetModePrivate,
- this.menuControlNetModePublic});
- this.menuControlNetMode.Name = "menuControlNetMode";
- this.menuControlNetMode.Size = new System.Drawing.Size(192, 22);
- this.menuControlNetMode.Text = "隧道网络模式设置(&M)";
- //
- // menuControlNetModePrivate
- //
- this.menuControlNetModePrivate.Name = "menuControlNetModePrivate";
- this.menuControlNetModePrivate.Size = new System.Drawing.Size(180, 22);
- this.menuControlNetModePrivate.Text = "专用网络 (Private)";
- //
- // menuControlNetModePublic
- //
- this.menuControlNetModePublic.Name = "menuControlNetModePublic";
- this.menuControlNetModePublic.Size = new System.Drawing.Size(180, 22);
- this.menuControlNetModePublic.Text = "公共网络 (Public)";
- //
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
@@ -486,9 +490,9 @@
private System.Windows.Forms.ToolStripMenuItem menuControlHeart;
private System.Windows.Forms.ToolStripMenuItem menuControlHeartStart;
private System.Windows.Forms.ToolStripMenuItem menuControlHeartStop;
- private System.Windows.Forms.ToolStripMenuItem menuControlNetMode;
- private System.Windows.Forms.ToolStripMenuItem menuControlNetModePrivate;
- private System.Windows.Forms.ToolStripMenuItem menuControlNetModePublic;
+ private System.Windows.Forms.ToolStripMenuItem menuSetShareMode;
+ private System.Windows.Forms.ToolStripMenuItem menuSetShareModeICS;
+ private System.Windows.Forms.ToolStripMenuItem menuSetShareModeNAT;
}
}
diff --git a/NetTunnelApp/MainForm.cs b/NetTunnelApp/MainForm.cs
index 1f154df..dd57ef0 100644
--- a/NetTunnelApp/MainForm.cs
+++ b/NetTunnelApp/MainForm.cs
@@ -63,8 +63,8 @@ public partial class MainForm : Form
var path = Environment.CurrentDirectory + "\\tunnelsdk_" +
string.Format("{0:yyyyMMdd}", DateTime.Now) + ".log";
- NetTunnelLib.InitTunnelSDKLog(path, LogLevel.LOG_DEBUG);
- NetTunnelLib.TunnelSDKInitEnv(Environment.CurrentDirectory, "http://xajhuang.com:9276", menuSetModeServer.Checked);
+ //NetTunnelLib.InitTunnelSDKLog(path, LogLevel.LOG_DEBUG);
+ NetTunnelLib.TunnelSDKInitEnv(Environment.CurrentDirectory, "http://xajhuang.com:9276", path, LogLevel.LOG_DEBUG, menuSetModeServer.Checked);
GetCurrentNetCard();
@@ -227,32 +227,14 @@ public partial class MainForm : Form
private void menuSetModeClient_Click(object sender, EventArgs e)
{
- var o = (ToolStripMenuItem)sender;
- if (o.Checked)
- {
- o.Checked = false;
- menuSetModeServer.Checked = true;
- }
- else
- {
- o.Checked = true;
- menuSetModeServer.Checked = false;
- }
+ menuSetModeClient.Checked = true;
+ menuSetModeServer.Checked = false;
}
private void menuSetModeServer_Click(object sender, EventArgs e)
{
- var o = (ToolStripMenuItem)sender;
- if (o.Checked)
- {
- o.Checked = false;
- menuSetModeClient.Checked = true;
- }
- else
- {
- o.Checked = true;
- menuSetModeClient.Checked = false;
- }
+ menuSetModeServer.Checked = true;
+ menuSetModeClient.Checked = false;
}
private void MainForm_SizeChanged(object sender, EventArgs e)
@@ -375,7 +357,7 @@ public partial class MainForm : Form
return;
}
- IPNetwork ipnetwork = IPNetwork.Parse(c?.IpAddr, c?.NetMask);
+ IPNetwork ipnetwork = IPNetwork.Parse("172.18.2.152", "255.255.255.0");
//IPNetwork cliNetwork = IPNetwork.Parse(_userConfig.cliAddress);
//MessageBox.Show(ipnetwork.Value);
@@ -462,4 +444,18 @@ public partial class MainForm : Form
MessageBox.Show("Error: " + ret.ToString());
}
}
+
+ private void menuSetShareModeICS_Click(object sender, EventArgs e)
+ {
+ menuSetShareModeNAT.Checked = false;
+ menuSetShareModeICS.Checked = true;
+ NetTunnelLib.SetCurrentNetShareMode(NET_SHARE_MODE.ICS_SHARE_MODE);
+ }
+
+ private void menuSetShareModeNAT_Click(object sender, EventArgs e)
+ {
+ menuSetShareModeICS.Checked = false;
+ menuSetShareModeNAT.Checked = true;
+ NetTunnelLib.SetCurrentNetShareMode(NET_SHARE_MODE.NAT_SHARE_MODE);
+ }
}
\ No newline at end of file
diff --git a/NetTunnelApp/NetTunnelLib.cs b/NetTunnelApp/NetTunnelLib.cs
index fa81701..b38e355 100644
--- a/NetTunnelApp/NetTunnelLib.cs
+++ b/NetTunnelApp/NetTunnelLib.cs
@@ -4,7 +4,7 @@ using System.Text;
namespace NetTunnelApp;
-public delegate void HeartCallBack(string msg, uint timeStamp);
+public delegate void HeartCallBack(string msg, uint timeStamp);
public enum ProtoCryptoType
{
@@ -26,6 +26,15 @@ public enum LogLevel
LOG_OFF
}
+public enum NET_SHARE_MODE
+{
+ ///< Internet Share Mode(ICS) 模式
+ ICS_SHARE_MODE = 0,
+
+ ///< Net Address Translation(NAT) 模式
+ NAT_SHARE_MODE = 1
+};
+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct VirtualMathineConfig
{
@@ -164,7 +173,8 @@ public struct WgCliConfig
public class NetTunnelLib
{
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern int TunnelSDKInitEnv(String workDir, String svrUrl, bool isWorkServer);
+ public static extern int TunnelSDKInitEnv(String workDir, String svrUrl, String pLogFile, LogLevel level,
+ bool isWorkServer);
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void TunnelSDKUnInit();
@@ -172,9 +182,6 @@ public class NetTunnelLib
[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);
@@ -210,7 +217,8 @@ public class NetTunnelLib
public static extern int RemoteCtrlSvrCfgUserTunnel(int vmid, String cliNetwork);
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
- public static extern int SetTunnelConfigure(String cliPrivateKey, String svrPublicKey, String svrNetwork, String cliNetwork, String svrAddr);
+ public static extern int SetTunnelConfigure(String cliPrivateKey, String svrPublicKey, String svrNetwork,
+ String cliNetwork, String svrAddr);
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int RemoteWireGuardControl(bool startOrStop);
@@ -221,6 +229,12 @@ public class NetTunnelLib
[DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int RemoteHeartControl(bool startOrStop, HeartCallBack cb);
+ [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern NET_SHARE_MODE GetCurrentNetShareMode();
+
+ [DllImport("NetTunnelSDK.dll", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void SetCurrentNetShareMode(NET_SHARE_MODE shareMode);
+
//[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/NetTunnelSDK/ControlService.cpp b/NetTunnelSDK/ControlService.cpp
index 6ad222e..12a8fc3 100644
--- a/NetTunnelSDK/ControlService.cpp
+++ b/NetTunnelSDK/ControlService.cpp
@@ -5,6 +5,8 @@
#include "globalcfg.h"
#include "httplib.h"
+#include "misc.h"
+#include "network.h"
#include "protocol.h"
#include "usrerr.h"
#include "user.h"
@@ -47,7 +49,8 @@ static void HttpResponseError(httplib::Response &pRes, int errCode, const TCHAR
}
int CreateControlService(PUSER_SERVER_CONFIG pSvr) {
- static WGSERVER_CONFIG g_curCliConfig = {};
+ static TCHAR g_CliNetwork[MAX_IP_LEN] = {};
+ static WGSERVER_CONFIG g_curCliConfig = {};
static std::mutex g_InterfaceMutex;
DWORD dwStatus = 0;
@@ -144,6 +147,10 @@ int CreateControlService(PUSER_SERVER_CONFIG pSvr) {
// 当前服务状态和需要执行的操作不同
if (isSvrStart != reqData.msgContent.isStart) {
if (reqData.msgContent.isStart) {
+ IP_INFO cliInfo;
+ IP_INFO tunnelInfo;
+ int retry = 3;
+
// 启动服务
ret = WireGuardInstallDefaultServerService(true);
if (ret != ERR_SUCCESS) {
@@ -153,6 +160,39 @@ int CreateControlService(PUSER_SERVER_CONFIG pSvr) {
g_InterfaceMutex.unlock();
return;
}
+ // 添加路由
+ if ((ret = GetIpV4InfoFromCIDR(g_CliNetwork, &cliInfo)) != ERR_SUCCESS) {
+ // 返回启动服务失败
+ SPDLOG_ERROR(TEXT("GetIpV4InfoFromCIDR ({1}) error: {0}"), ret, g_CliNetwork);
+ HttpResponseError(res, ret, TEXT("Parse IpAddress error."));
+ g_InterfaceMutex.unlock();
+ return;
+ }
+
+ if ((ret = GetIpV4InfoFromCIDR(g_UserSvrCfg.svrAddress, &tunnelInfo)) != ERR_SUCCESS) {
+ // 返回启动服务失败
+ SPDLOG_ERROR(TEXT("GetIpV4InfoFromCIDR ({1}) error: {0}"), ret, g_UserSvrCfg.svrAddress);
+ HttpResponseError(res, ret, TEXT("Parse tunnel ip address error."));
+ g_InterfaceMutex.unlock();
+ return;
+ }
+
+ do {
+ ret = AddRouteTable(cliInfo.ip, cliInfo.netmask, tunnelInfo.ip);
+ Sleep(1000);
+ } while (ret != ERR_SUCCESS && retry--);
+
+ if (ret != ERR_SUCCESS) {
+ // 返回启动服务失败
+ SPDLOG_ERROR(TEXT("Add Route {1}/{2} gateway {3} error: {0}"),
+ ret,
+ cliInfo.ip,
+ cliInfo.netmask,
+ tunnelInfo.ip);
+ HttpResponseError(res, ret, TEXT("Parse tunnel ip address error."));
+ g_InterfaceMutex.unlock();
+ return;
+ }
} else {
if ((ret = WireGuardUnInstallServerService(GetGlobalCfgInfo()->userCfg.userName)) != ERR_SUCCESS) {
// 返回停止服务失败
@@ -208,6 +248,7 @@ int CreateControlService(PUSER_SERVER_CONFIG pSvr) {
StringCbCopy(g_curCliConfig.Address, 32, g_UserSvrCfg.svrAddress);
StringCbCopy(g_curCliConfig.PrivateKey, 64, g_UserSvrCfg.svrPrivateKey);
StringCbCopy(g_curCliConfig.CliPubKey, 64, reqData.msgContent.cliPublicKey.c_str());
+ StringCbCopy(g_CliNetwork, MAX_IP_LEN, reqData.msgContent.cliNetwork.c_str());
StringCbPrintf(g_curCliConfig.AllowNet,
256,
TEXT("%s,%s"),
@@ -233,7 +274,7 @@ int CreateControlService(PUSER_SERVER_CONFIG pSvr) {
// 设置路由表
#endif
- // 返回当前隧道信息
+ // 返回当前隧道信息
rsp.msgContent.errCode = ERR_SUCCESS;
rsp.msgContent.errMessage = TEXT("OK");
rsp.msgContent.svrNetwork = g_UserSvrCfg.svrAddress;
diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj b/NetTunnelSDK/NetTunnelSDK.vcxproj
index 87aa23e..0461a18 100644
--- a/NetTunnelSDK/NetTunnelSDK.vcxproj
+++ b/NetTunnelSDK/NetTunnelSDK.vcxproj
@@ -119,6 +119,7 @@
Windows
true
false
+ .\WinDivert\x64;%(AdditionalLibraryDirectories)
copy /y $(TargetDir)*.dll $(SolutionDir)\NetTunnelApp\bin\$(ConfigurationName)\
@@ -160,6 +161,7 @@
+
@@ -177,6 +179,7 @@
+
NotUsing
diff --git a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters
index 60d6eb2..3487057 100644
--- a/NetTunnelSDK/NetTunnelSDK.vcxproj.filters
+++ b/NetTunnelSDK/NetTunnelSDK.vcxproj.filters
@@ -78,6 +78,9 @@
头文件\http
+
+ 头文件
+
@@ -119,6 +122,9 @@
源文件
+
+ 源文件\network
+
diff --git a/NetTunnelSDK/ProxyService.cpp b/NetTunnelSDK/ProxyService.cpp
new file mode 100644
index 0000000..825c01d
--- /dev/null
+++ b/NetTunnelSDK/ProxyService.cpp
@@ -0,0 +1,377 @@
+#include "pch.h"
+#include "WinDivert/include/windivert.h"
+
+#include
+#include
+#include "globalcfg.h"
+#include "usrerr.h"
+
+#include
+
+#pragma comment(lib, "WinDivert.lib")
+
+typedef enum {
+ PROXY_TCP = 1 << 0,
+ PROXY_UDP = 1 << 1,
+} PROXY_PORTO_TYPE;
+
+typedef struct {
+ bool isRunning;
+ HANDLE proxyThread;
+ HANDLE proxyHandle;
+ bool isExitSvr;
+} UDP_PROXY_CTX, *PUDP_PROXY_CTX;
+
+typedef struct {
+ SOCKET proxySock;
+ SOCKET reservePortSock;
+ SOCKET altSock;
+ bool isRunning;
+ UINT16 proxyPort;
+ UINT16 altPort;
+ HANDLE proxyThread;
+ HANDLE proxyHandle;
+ bool isExitSvr;
+} TCP_PROXY_CTX, *PTCP_PORXY_CTX;
+
+typedef struct {
+ int proType;
+ TCHAR streamFilter[1024];
+ TCHAR targetIp[MAX_IP_LEN];
+ UINT16 targetPort;
+ int vmId;
+ int svrId;
+ TCP_PROXY_CTX tcpCtx;
+ UDP_PROXY_CTX udpCtx;
+} PROXY_INFO, *PPROXY_INFO;
+
+typedef struct {
+ SOCKET s;
+ PPROXY_INFO pCtx;
+ bool inbound;
+ in_addr dest;
+} PROXY_CONNECTION_CONFIG, *PPROXY_CONNECTION_CONFIG;
+
+static std::unordered_map g_ProxyColleagues;
+
+static int NewAvaliableSocket(SOCKET *pSock, UINT16 *pPort) {
+ const int reusedAddr = 1;
+ sockaddr_in proxySvrAddr {};
+ sockaddr_in bindAddr {};
+ int ret;
+ int addrSize = sizeof(sockaddr_in);
+ const SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (sock == INVALID_SOCKET) {
+ SPDLOG_ERROR(TEXT("Cretate TCP Socket error: {0}"), WSAGetLastError());
+ return -ERR_SOCKET_BIND_PORT;
+ }
+
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&reusedAddr), sizeof(int)) ==
+ SOCKET_ERROR) {
+ SPDLOG_ERROR(TEXT("Failed to set socket optino SO_REUSEADDR ({0}})"), WSAGetLastError());
+ closesocket(sock);
+ return -ERR_SOCKET_SET_OPT;
+ }
+
+ proxySvrAddr.sin_family = AF_INET;
+ proxySvrAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ proxySvrAddr.sin_port = htons(0);
+
+ if (bind(sock, reinterpret_cast(&proxySvrAddr), sizeof(proxySvrAddr)) == SOCKET_ERROR) {
+ SPDLOG_ERROR(TEXT("Failed to bind socket ({0})"), WSAGetLastError());
+ closesocket(sock);
+ return -ERR_SOCKET_BIND;
+ }
+
+ if (getsockname(sock, reinterpret_cast(&bindAddr), &addrSize) != 0) {
+ SPDLOG_ERROR(TEXT("Failed to get socket bind port ({0})"), WSAGetLastError());
+ closesocket(sock);
+ return -ERR_SOCKET_GET_OPT;
+ }
+
+ *pSock = sock;
+ *pPort = ntohs(bindAddr.sin_port);
+
+ return ERR_SUCCESS;
+}
+
+static DWORD proxyForwardCb(LPVOID lpParameter) {
+ return 0;
+}
+
+static DWORD proxyConnCb(LPVOID lpParameter) {
+ const auto p = static_cast(lpParameter);
+ sockaddr_in altAddr {};
+ SOCKET altSock;
+ HANDLE thread;
+ SOCKET connSock = p->s;
+ in_addr dest = p->dest;
+ PPROXY_INFO pInfo = p->pCtx;
+ PPROXY_CONNECTION_CONFIG pCfgProxySvr, pCfgAltSvr;
+
+ HeapFree(GetProcessHeap(), 0, p);
+
+ altSock = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (altSock == INVALID_SOCKET) {
+ SPDLOG_ERROR(TEXT("Cretate TCP Socket error: {0}"), WSAGetLastError());
+ closesocket(connSock);
+ return 0;
+ }
+
+ memset(&altAddr, 0, sizeof(altAddr));
+ altAddr.sin_family = AF_INET;
+ altAddr.sin_port = htons(pInfo->tcpCtx.altPort);
+ altAddr.sin_addr = dest;
+
+ if (connect(altSock, reinterpret_cast(&altAddr), sizeof(altAddr)) == SOCKET_ERROR) {
+ SPDLOG_ERROR(TEXT("Failed to connect socket ({0})"), WSAGetLastError());
+ closesocket(connSock);
+ closesocket(altSock);
+ return 0;
+ }
+
+ pInfo->tcpCtx.altSock = altSock;
+
+ pCfgProxySvr = static_cast(
+ HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG)));
+
+ if (pCfgProxySvr == nullptr) {
+ SPDLOG_ERROR(TEXT("Malloc {0} bytes error."), sizeof(PROXY_CONNECTION_CONFIG));
+ closesocket(connSock);
+ closesocket(altSock);
+ return 0;
+ }
+
+ pCfgAltSvr = static_cast(HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG)));
+
+ if (pCfgAltSvr == nullptr) {
+ SPDLOG_ERROR(TEXT("Malloc {0} bytes error."), sizeof(PROXY_CONNECTION_CONFIG));
+ closesocket(connSock);
+ closesocket(altSock);
+ free(pCfgProxySvr);
+ return 0;
+ }
+
+ thread = CreateThread(nullptr, // Thread attributes
+ 0, // Stack size (0 = use default)
+ proxyForwardCb, // Thread start address
+ pCfgProxySvr, // Parameter to pass to the thread
+ 0, // Creation flags
+ nullptr); // Thread id
+
+ if (thread == nullptr) {
+ SPDLOG_ERROR(TEXT("Failed to create thread ({0})"), GetLastError());
+ closesocket(connSock);
+ closesocket(altSock);
+ free(pCfgProxySvr);
+ free(pCfgAltSvr);
+ return 0;
+ }
+
+ return 0;
+}
+
+static int StartTcpProxyService(PPROXY_INFO pInfo) {
+ pInfo->tcpCtx.isExitSvr = false;
+
+ if (listen(pInfo->tcpCtx.proxySock, SOMAXCONN) == SOCKET_ERROR) {
+ SPDLOG_ERROR(TEXT("Failed to listen socket ({0})"), WSAGetLastError());
+ closesocket(pInfo->tcpCtx.proxySock);
+ return -ERR_SOCKET_LISTEN;
+ }
+
+ pInfo->tcpCtx.proxyThread = CreateThread(
+ nullptr, // Thread attributes
+ 0, // Stack size (0 = use default)
+ [](LPVOID lpParameter) {
+ const auto p = static_cast(lpParameter);
+
+ while (!p->tcpCtx.isExitSvr) {
+ PPROXY_CONNECTION_CONFIG pCfg;
+ sockaddr_in connAddr {};
+ int size = sizeof(connAddr);
+
+ SOCKET s = accept(p->tcpCtx.proxySock, reinterpret_cast(&connAddr), &size);
+
+ if (s == INVALID_SOCKET) {
+ continue;
+ }
+
+ pCfg = static_cast(
+ HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_CONNECTION_CONFIG)));
+
+ if (pCfg) {
+ HANDLE thread;
+ pCfg->s = s;
+ pCfg->dest = connAddr.sin_addr;
+ pCfg->pCtx = p;
+
+ thread = CreateThread(nullptr,
+ 0,
+ proxyConnCb, // Thread start address
+ pCfg, // Parameter to pass to the thread
+ 0,
+ nullptr);
+
+ if (thread == nullptr) {
+ closesocket(s);
+ HeapFree(GetProcessHeap(), 0, pCfg);
+ continue;
+ }
+
+ CloseHandle(thread);
+ }
+ }
+
+ return static_cast(0);
+ }, // Thread start address
+ pInfo, // Parameter to pass to the thread
+ 0, // Creation flags
+ nullptr); // Thread id
+
+ if (pInfo->tcpCtx.proxyThread == nullptr) {
+ SPDLOG_ERROR(TEXT("Create TCP Listen Thread Error ({0})"), GetLastError());
+ return -ERR_CREATE_THREAD;
+ }
+}
+
+int CreatePorxyService(int proType, const TCHAR *pTargetIp, int targetPort, int vmId, int svrId) {
+ //int CreatePorxyService() {
+ int ret;
+ static HANDLE hDriver;
+ PPROXY_INFO pInfo;
+ std::string key;
+ std::unordered_map::iterator iter;
+
+ // 查找先前代理是否存在
+ key = std::string(pTargetIp) + ":" + std::to_string(targetPort);
+
+ if ((iter = g_ProxyColleagues.find(key)) != g_ProxyColleagues.end()) {
+ pInfo = iter->second;
+ // 如果配置完全相同则直接返回
+ if (pInfo->vmId == vmId && pInfo->svrId == svrId && pInfo->proType == proType) {
+ return ERR_SUCCESS;
+ } else {
+ pInfo->vmId = vmId;
+ pInfo->svrId = svrId;
+ pInfo->proType = proType;
+ }
+ } else {
+ // 创建新的代理配置
+ pInfo = static_cast(HeapAlloc(GetProcessHeap(), 0, sizeof(PROXY_INFO)));
+
+ if (pInfo == nullptr) {
+ SPDLOG_ERROR(TEXT("Error allocating {0} bytes memory "), sizeof(PROXY_INFO));
+ return -ERR_MALLOC_MEMORY;
+ }
+
+ memset(pInfo, 0, sizeof(PROXY_INFO));
+ }
+
+ memset(pInfo->streamFilter, 0, 1024);
+
+ // 重构过滤器
+ if (pInfo->proType & PROXY_UDP) {
+ StringCbPrintf(pInfo->streamFilter, 1024, TEXT("(udp.DstPort == %d)"), targetPort);
+ //StringCbPrintf(pFilter, 1024, TEXT("tcp && remotePort == 9276"));
+ }
+
+ if (pInfo->proType & PROXY_TCP) {
+ TCHAR tmpFilter[1024];
+
+ // 预先分配代理和转发 Socket
+ if ((ret = NewAvaliableSocket(&pInfo->tcpCtx.proxySock, &pInfo->tcpCtx.proxyPort)) != ERR_SUCCESS) {
+ return ret;
+ }
+
+ if ((ret = NewAvaliableSocket(&pInfo->tcpCtx.reservePortSock, &pInfo->tcpCtx.altPort)) != ERR_SUCCESS) {
+ return ret;
+ }
+
+ // 构建过滤器
+ StringCbPrintf(tmpFilter,
+ 1024,
+ TEXT("(tcp.DstPort == %d or tcp.DstPort == %d or tcp.DstPort == %d or tcp.SrcPort == %d or "
+ "tcp.SrcPort == %d or tcp.SrcPort == %d)"),
+ targetPort,
+ pInfo->tcpCtx.proxyPort,
+ pInfo->tcpCtx.altPort,
+ targetPort,
+ pInfo->tcpCtx.proxyPort,
+ pInfo->tcpCtx.altPort);
+
+ if (lstrlen(pInfo->streamFilter) > 0) {
+ StringCbCat(pInfo->streamFilter, 1024, TEXT(" or "));
+ StringCbCat(pInfo->streamFilter, 1024, tmpFilter);
+ } else {
+ StringCbCopy(pInfo->streamFilter, 1024, tmpFilter);
+ }
+ }
+
+ // 启动代理服务
+ if ((ret = StartTcpProxyService(pInfo)) != ERR_SUCCESS) {
+ return ret;
+ }
+
+ hDriver = WinDivertOpen(pInfo->streamFilter, WINDIVERT_LAYER_NETWORK, 0, 0);
+
+ if (hDriver == INVALID_HANDLE_VALUE) {
+ //ERROR_INSUFFICIENT_BUFFER
+ SPDLOG_ERROR(TEXT("Open Driver With Filter \"{1}\" Error: {0}"), GetLastError(), pInfo->streamFilter);
+ return -ERR_SYS_CALL;
+ }
+
+ CreateThread(
+ nullptr, // Thread attributes
+ 0, // Stack size (0 = use default)
+ [](LPVOID lpParameter) {
+ const HANDLE h = lpParameter;
+ unsigned char packet[0xFFFF];
+ UINT packet_len;
+ WINDIVERT_ADDRESS addr;
+
+ while (true) {
+ if (!WinDivertRecv(h, packet, 0xFFFF, &packet_len, &addr)) {
+ SPDLOG_ERROR(TEXT("failed to read packet ({0})"), GetLastError());
+ continue;
+ }
+
+ switch (addr.Event) {
+ case WINDIVERT_EVENT_SOCKET_BIND:
+ SPDLOG_ERROR("BIND");
+ break;
+ case WINDIVERT_EVENT_SOCKET_LISTEN:
+
+ SPDLOG_ERROR("LISTEN");
+ break;
+ case WINDIVERT_EVENT_SOCKET_CONNECT:
+
+ SPDLOG_ERROR("CONNECT: {0:x}, {1:x}", addr.Socket.EndpointId, addr.Socket.ParentEndpointId);
+ break;
+ case WINDIVERT_EVENT_SOCKET_ACCEPT:
+
+ SPDLOG_ERROR("ACCEPT");
+ break;
+ case WINDIVERT_EVENT_SOCKET_CLOSE:
+
+ SPDLOG_ERROR("CLOSE: {0:x}, {1:x}", addr.Socket.EndpointId, addr.Socket.ParentEndpointId);
+ break;
+ default:
+ SPDLOG_ERROR(TEXT("***({0})"), static_cast(addr.Event));
+ break;
+ }
+
+ /*if (!WinDivertSendEx(h, packet, packet_len, nullptr, 0, &addr, sizeof(WINDIVERT_ADDRESS), nullptr)) {
+ SPDLOG_ERROR(TEXT("warning: failed to reinject packet ({0})\n"), GetLastError());
+ }*/
+ }
+
+ return static_cast(0);
+ }, // Thread start address
+ hDriver, // Parameter to pass to the thread
+ 0, // Creation flags
+ nullptr); // Thread id
+ return 0;
+}
\ No newline at end of file
diff --git a/NetTunnelSDK/UserManager.cpp b/NetTunnelSDK/UserManager.cpp
index c03f0f2..3b14729 100644
--- a/NetTunnelSDK/UserManager.cpp
+++ b/NetTunnelSDK/UserManager.cpp
@@ -94,6 +94,13 @@ int RemoteWireGuardControl(bool isStart) {
int LocalWireGuardControl(bool isStart, bool setPrivateMode) {
int ret;
bool chkStatus = false;
+ int ifInetlnetIndex, ifWireGuardIndex;
+
+ // 获取 Intelnet 网络网卡 Index
+ if ((ret = GetInternetIfIndex(&ifInetlnetIndex)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call GetInternetIfIndex error: {0}"), ret);
+ return ret;
+ }
// 判断先前是否启动过服务
if ((ret = IsWireGuardServerRunning(GetGlobalCfgInfo()->userCfg.userName, &chkStatus)) != ERR_SUCCESS) {
@@ -101,6 +108,7 @@ int LocalWireGuardControl(bool isStart, bool setPrivateMode) {
return ret;
}
+ // 先停止以前启动的隧道服务
if (chkStatus) {
if ((ret = WireGuardUnInstallServerService(GetGlobalCfgInfo()->userCfg.userName)) != ERR_SUCCESS) {
// 返回停止服务失败
@@ -109,6 +117,20 @@ int LocalWireGuardControl(bool isStart, bool setPrivateMode) {
}
}
+ // 检查 Internet 网络共享状态
+ if ((ret = GetNetIntelnetConnectionSharing(ifInetlnetIndex, &chkStatus)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call GetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+
+ // 关闭 Intelnet 网络连接共享
+ if (chkStatus) {
+ if ((ret = SetNetIntelnetConnectionSharing(ifInetlnetIndex, false, false)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call SetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+ }
+
if (isStart) {
// 启动服务
ret = WireGuardInstallDefaultServerService(true);
@@ -118,19 +140,78 @@ int LocalWireGuardControl(bool isStart, bool setPrivateMode) {
return ret;
}
- if ((ret = GetNetConnectionNetworkCategory(GetGlobalCfgInfo()->userCfg.userName, &chkStatus)) != ERR_SUCCESS) {
- SPDLOG_ERROR(TEXT("Call GetNetConnectionNetworkCategory error: {0}"), ret);
- return ret;
- }
-
- // 检查网卡模式是否和设定值一致
- if (setPrivateMode != chkStatus) {
- if ((ret = SetNetConnectionNetworkCategory(GetGlobalCfgInfo()->userCfg.userName, setPrivateMode)) !=
+ if (GetCurrentNetShareMode() == ICS_SHARE_MODE) {
+ // 获取 WireGuard 隧道网络网卡 Index
+ if ((ret = GetInterfaceIfIndexByName(GetGlobalCfgInfo()->userCfg.userName, &ifWireGuardIndex)) !=
ERR_SUCCESS) {
- SPDLOG_ERROR(TEXT("Call SetNetConnectionNetworkCategory error: {0}"), ret);
+ SPDLOG_ERROR(TEXT("Call GetInterfaceIfIndexByName error: {0}"), ret);
+ return ret;
+ }
+
+ // 启动 WireGard 网络 ICS 服务为私有网络
+ if ((ret = SetNetIntelnetConnectionSharing(ifWireGuardIndex, true, true)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call SetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+
+ // 启动 Intelnet 网络 ICS 服务为公共网络
+ if ((ret = SetNetIntelnetConnectionSharing(ifInetlnetIndex, true, false)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call SetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+
+ // 校验 ICS 共享状态
+ // 检查 WireGuard 网络共享状态
+ if ((ret = GetNetIntelnetConnectionSharing(ifWireGuardIndex, &chkStatus)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call GetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+
+ if (!chkStatus) {
+ SPDLOG_ERROR(TEXT("WireGuard network ICS error"));
+ return -ERR_NET_WIREGUARD_ICS;
+ }
+
+ // 检查 WireGuard 网络共享状态
+ if ((ret = GetNetIntelnetConnectionSharing(ifInetlnetIndex, &chkStatus)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call GetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+
+ if (!chkStatus) {
+ SPDLOG_ERROR(TEXT("Internet network ICS error"));
+ return -ERR_NET_WIREGUARD_ICS;
+ }
+
+ SPDLOG_INFO(TEXT("Net Share Service Work now on ICS mode: {0}"), GetGlobalCfgInfo()->userCfg.userName);
+ } else if (GetCurrentNetShareMode() == NAT_SHARE_MODE) {
+ IP_INFO ipInfo;
+ TCHAR ipNat[MAX_IP_LEN];
+ GetIpV4InfoFromCIDR(GetGlobalCfgInfo()->userCfg.cliConfig.cliAddress, &ipInfo);
+ StringCbPrintf(ipNat, MAX_IP_LEN, TEXT("%s/%d"), ipInfo.hostmax, ipInfo.prefix);
+
+ // 检查 WireGuard 网络共享状态
+ if ((ret = SetNATRule(GetGlobalCfgInfo()->userCfg.userName, ipNat)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call GetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+
+ SPDLOG_INFO(TEXT("Net Share Service Work now on NAT mode: {0}_nat --> {1}"),
+ GetGlobalCfgInfo()->userCfg.userName,
+ ipNat);
+ } else {
+ SPDLOG_ERROR(TEXT("Not support Net Share Type: {0}"), static_cast(GetCurrentNetShareMode()));
+ return -ERR_UN_SUPPORT;
+ }
+ } else {
+ if (GetCurrentNetShareMode() == NAT_SHARE_MODE) {
+ // 检查 WireGuard 网络共享状态
+ if ((ret = RemoveNATRule(GetGlobalCfgInfo()->userCfg.userName)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call RemoveNATRule error: {0}"), ret);
return ret;
}
}
+ SPDLOG_INFO(TEXT("Net Share Service Stoped: {0}"), GetGlobalCfgInfo()->userCfg.userName);
}
return ERR_SUCCESS;
@@ -176,6 +257,13 @@ int RemoteCtrlSvrCfgUserTunnel(int vmId, const TCHAR *pCliNetwork) {
pUserCfg->cliAddress,
rsp.msgContent.svrNetwork.c_str(),
pUserCfg->pVMConfig[i].scgTunnelGw);
+
+ if (ret != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("SetTunnelConfigure Error: {0}"), ret);
+ return ret;
+ }
+
+ GetGlobalCfgInfo()->curConnVmId = vmId;
return ERR_SUCCESS;
}
}
@@ -191,6 +279,7 @@ int SetTunnelConfigure(const TCHAR *pCliPrivateKey,
const TCHAR *pSvrEndPoint) {
int ret;
bool isSvrStart = false;
+ int ifInetlnetIndex;
IP_INFO tunnelInfo = {};
IP_INFO svrInfo = {};
WGCLIENT_CONFIG cliCfg = {};
@@ -245,6 +334,38 @@ int SetTunnelConfigure(const TCHAR *pCliPrivateKey,
}
}
+ // 获取 Intelnet 网络网卡 Index
+ if ((ret = GetInternetIfIndex(&ifInetlnetIndex)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call GetInternetIfIndex error: {0}"), ret);
+ return ret;
+ }
+
+ if (GetCurrentNetShareMode() == ICS_SHARE_MODE) {
+ // 检查 Internet 网络共享状态
+ if ((ret = GetNetIntelnetConnectionSharing(ifInetlnetIndex, &isSvrStart)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call GetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+
+ // 关闭 Intelnet 网络连接共享
+ if (isSvrStart) {
+ if ((ret = SetNetIntelnetConnectionSharing(ifInetlnetIndex, false, false)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call SetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+ }
+ }
+
+#if 0
+ if (GetCurrentNetShareMode() == NAT_SHARE_MODE) {
+ // 清理旧的 NAT 配置
+ if ((ret = RemoveNATRule(GetGlobalCfgInfo()->userCfg.userName)) != ERR_SUCCESS) {
+ SPDLOG_ERROR(TEXT("Call GetNetIntelnetConnectionSharing error: {0}"), ret);
+ return ret;
+ }
+ }
+#endif
+
ret = GetIpV4InfoFromCIDR(pSvrTunnelAddr, &tunnelInfo);
if (ret != ERR_SUCCESS) {
diff --git a/NetTunnelSDK/WinDivert/include/windivert.h b/NetTunnelSDK/WinDivert/include/windivert.h
new file mode 100644
index 0000000..fc63adf
--- /dev/null
+++ b/NetTunnelSDK/WinDivert/include/windivert.h
@@ -0,0 +1,630 @@
+/*
+ * windivert.h
+ * (C) 2019, all rights reserved,
+ *
+ * This file is part of WinDivert.
+ *
+ * WinDivert is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see .
+ *
+ * WinDivert is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __WINDIVERT_H
+#define __WINDIVERT_H
+
+#ifndef WINDIVERT_KERNEL
+#include
+#endif /* WINDIVERT_KERNEL */
+
+#ifndef WINDIVERTEXPORT
+#define WINDIVERTEXPORT extern __declspec(dllimport)
+#endif /* WINDIVERTEXPORT */
+
+#ifdef __MINGW32__
+#define __in
+#define __in_opt
+#define __out
+#define __out_opt
+#define __inout
+#define __inout_opt
+#include
+#define INT8 int8_t
+#define UINT8 uint8_t
+#define INT16 int16_t
+#define UINT16 uint16_t
+#define INT32 int32_t
+#define UINT32 uint32_t
+#define INT64 int64_t
+#define UINT64 uint64_t
+#endif /* __MINGW32__ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************/
+/* WINDIVERT API */
+/****************************************************************************/
+
+/*
+ * WinDivert layers.
+ */
+typedef enum
+{
+ WINDIVERT_LAYER_NETWORK = 0, /* Network layer. */
+ WINDIVERT_LAYER_NETWORK_FORWARD = 1,/* Network layer (forwarded packets) */
+ WINDIVERT_LAYER_FLOW = 2, /* Flow layer. */
+ WINDIVERT_LAYER_SOCKET = 3, /* Socket layer. */
+ WINDIVERT_LAYER_REFLECT = 4, /* Reflect layer. */
+} WINDIVERT_LAYER, *PWINDIVERT_LAYER;
+
+/*
+ * WinDivert NETWORK and NETWORK_FORWARD layer data.
+ */
+typedef struct
+{
+ UINT32 IfIdx; /* Packet's interface index. */
+ UINT32 SubIfIdx; /* Packet's sub-interface index. */
+} WINDIVERT_DATA_NETWORK, *PWINDIVERT_DATA_NETWORK;
+
+/*
+ * WinDivert FLOW layer data.
+ */
+typedef struct
+{
+ UINT64 EndpointId; /* Endpoint ID. */
+ UINT64 ParentEndpointId; /* Parent endpoint ID. */
+ UINT32 ProcessId; /* Process ID. */
+ UINT32 LocalAddr[4]; /* Local address. */
+ UINT32 RemoteAddr[4]; /* Remote address. */
+ UINT16 LocalPort; /* Local port. */
+ UINT16 RemotePort; /* Remote port. */
+ UINT8 Protocol; /* Protocol. */
+} WINDIVERT_DATA_FLOW, *PWINDIVERT_DATA_FLOW;
+
+/*
+ * WinDivert SOCKET layer data.
+ */
+typedef struct
+{
+ UINT64 EndpointId; /* Endpoint ID. */
+ UINT64 ParentEndpointId; /* Parent Endpoint ID. */
+ UINT32 ProcessId; /* Process ID. */
+ UINT32 LocalAddr[4]; /* Local address. */
+ UINT32 RemoteAddr[4]; /* Remote address. */
+ UINT16 LocalPort; /* Local port. */
+ UINT16 RemotePort; /* Remote port. */
+ UINT8 Protocol; /* Protocol. */
+} WINDIVERT_DATA_SOCKET, *PWINDIVERT_DATA_SOCKET;
+
+/*
+ * WinDivert REFLECTION layer data.
+ */
+typedef struct
+{
+ INT64 Timestamp; /* Handle open time. */
+ UINT32 ProcessId; /* Handle process ID. */
+ WINDIVERT_LAYER Layer; /* Handle layer. */
+ UINT64 Flags; /* Handle flags. */
+ INT16 Priority; /* Handle priority. */
+} WINDIVERT_DATA_REFLECT, *PWINDIVERT_DATA_REFLECT;
+
+/*
+ * WinDivert address.
+ */
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4201)
+#endif
+typedef struct
+{
+ INT64 Timestamp; /* Packet's timestamp. */
+ UINT32 Layer:8; /* Packet's layer. */
+ UINT32 Event:8; /* Packet event. */
+ UINT32 Sniffed:1; /* Packet was sniffed? */
+ UINT32 Outbound:1; /* Packet is outound? */
+ UINT32 Loopback:1; /* Packet is loopback? */
+ UINT32 Impostor:1; /* Packet is impostor? */
+ UINT32 IPv6:1; /* Packet is IPv6? */
+ UINT32 IPChecksum:1; /* Packet has valid IPv4 checksum? */
+ UINT32 TCPChecksum:1; /* Packet has valid TCP checksum? */
+ UINT32 UDPChecksum:1; /* Packet has valid UDP checksum? */
+ UINT32 Reserved1:8;
+ UINT32 Reserved2;
+ union
+ {
+ WINDIVERT_DATA_NETWORK Network; /* Network layer data. */
+ WINDIVERT_DATA_FLOW Flow; /* Flow layer data. */
+ WINDIVERT_DATA_SOCKET Socket; /* Socket layer data. */
+ WINDIVERT_DATA_REFLECT Reflect; /* Reflect layer data. */
+ UINT8 Reserved3[64];
+ };
+} WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS;
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+/*
+ * WinDivert events.
+ */
+typedef enum
+{
+ WINDIVERT_EVENT_NETWORK_PACKET = 0, /* Network packet. */
+ WINDIVERT_EVENT_FLOW_ESTABLISHED = 1,
+ /* Flow established. */
+ WINDIVERT_EVENT_FLOW_DELETED = 2, /* Flow deleted. */
+ WINDIVERT_EVENT_SOCKET_BIND = 3, /* Socket bind. */
+ WINDIVERT_EVENT_SOCKET_CONNECT = 4, /* Socket connect. */
+ WINDIVERT_EVENT_SOCKET_LISTEN = 5, /* Socket listen. */
+ WINDIVERT_EVENT_SOCKET_ACCEPT = 6, /* Socket accept. */
+ WINDIVERT_EVENT_SOCKET_CLOSE = 7, /* Socket close. */
+ WINDIVERT_EVENT_REFLECT_OPEN = 8, /* WinDivert handle opened. */
+ WINDIVERT_EVENT_REFLECT_CLOSE = 9, /* WinDivert handle closed. */
+} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
+
+/*
+ * WinDivert flags.
+ */
+#define WINDIVERT_FLAG_SNIFF 0x0001
+#define WINDIVERT_FLAG_DROP 0x0002
+#define WINDIVERT_FLAG_RECV_ONLY 0x0004
+#define WINDIVERT_FLAG_READ_ONLY WINDIVERT_FLAG_RECV_ONLY
+#define WINDIVERT_FLAG_SEND_ONLY 0x0008
+#define WINDIVERT_FLAG_WRITE_ONLY WINDIVERT_FLAG_SEND_ONLY
+#define WINDIVERT_FLAG_NO_INSTALL 0x0010
+#define WINDIVERT_FLAG_FRAGMENTS 0x0020
+
+/*
+ * WinDivert parameters.
+ */
+typedef enum
+{
+ WINDIVERT_PARAM_QUEUE_LENGTH = 0, /* Packet queue length. */
+ WINDIVERT_PARAM_QUEUE_TIME = 1, /* Packet queue time. */
+ WINDIVERT_PARAM_QUEUE_SIZE = 2, /* Packet queue size. */
+ WINDIVERT_PARAM_VERSION_MAJOR = 3, /* Driver version (major). */
+ WINDIVERT_PARAM_VERSION_MINOR = 4, /* Driver version (minor). */
+} WINDIVERT_PARAM, *PWINDIVERT_PARAM;
+#define WINDIVERT_PARAM_MAX WINDIVERT_PARAM_VERSION_MINOR
+
+/*
+ * WinDivert shutdown parameter.
+ */
+typedef enum
+{
+ WINDIVERT_SHUTDOWN_RECV = 0x1, /* Shutdown recv. */
+ WINDIVERT_SHUTDOWN_SEND = 0x2, /* Shutdown send. */
+ WINDIVERT_SHUTDOWN_BOTH = 0x3, /* Shutdown recv and send. */
+} WINDIVERT_SHUTDOWN, *PWINDIVERT_SHUTDOWN;
+#define WINDIVERT_SHUTDOWN_MAX WINDIVERT_SHUTDOWN_BOTH
+
+#ifndef WINDIVERT_KERNEL
+
+/*
+ * Open a WinDivert handle.
+ */
+WINDIVERTEXPORT HANDLE WinDivertOpen(
+ __in const char *filter,
+ __in WINDIVERT_LAYER layer,
+ __in INT16 priority,
+ __in UINT64 flags);
+
+/*
+ * Receive (read) a packet from a WinDivert handle.
+ */
+WINDIVERTEXPORT BOOL WinDivertRecv(
+ __in HANDLE handle,
+ __out_opt VOID *pPacket,
+ __in UINT packetLen,
+ __out_opt UINT *pRecvLen,
+ __out_opt WINDIVERT_ADDRESS *pAddr);
+
+/*
+ * Receive (read) a packet from a WinDivert handle.
+ */
+WINDIVERTEXPORT BOOL WinDivertRecvEx(
+ __in HANDLE handle,
+ __out_opt VOID *pPacket,
+ __in UINT packetLen,
+ __out_opt UINT *pRecvLen,
+ __in UINT64 flags,
+ __out WINDIVERT_ADDRESS *pAddr,
+ __inout_opt UINT *pAddrLen,
+ __inout_opt LPOVERLAPPED lpOverlapped);
+
+/*
+ * Send (write/inject) a packet to a WinDivert handle.
+ */
+WINDIVERTEXPORT BOOL WinDivertSend(
+ __in HANDLE handle,
+ __in const VOID *pPacket,
+ __in UINT packetLen,
+ __out_opt UINT *pSendLen,
+ __in const WINDIVERT_ADDRESS *pAddr);
+
+/*
+ * Send (write/inject) a packet to a WinDivert handle.
+ */
+WINDIVERTEXPORT BOOL WinDivertSendEx(
+ __in HANDLE handle,
+ __in const VOID *pPacket,
+ __in UINT packetLen,
+ __out_opt UINT *pSendLen,
+ __in UINT64 flags,
+ __in const WINDIVERT_ADDRESS *pAddr,
+ __in UINT addrLen,
+ __inout_opt LPOVERLAPPED lpOverlapped);
+
+/*
+ * Shutdown a WinDivert handle.
+ */
+WINDIVERTEXPORT BOOL WinDivertShutdown(
+ __in HANDLE handle,
+ __in WINDIVERT_SHUTDOWN how);
+
+/*
+ * Close a WinDivert handle.
+ */
+WINDIVERTEXPORT BOOL WinDivertClose(
+ __in HANDLE handle);
+
+/*
+ * Set a WinDivert handle parameter.
+ */
+WINDIVERTEXPORT BOOL WinDivertSetParam(
+ __in HANDLE handle,
+ __in WINDIVERT_PARAM param,
+ __in UINT64 value);
+
+/*
+ * Get a WinDivert handle parameter.
+ */
+WINDIVERTEXPORT BOOL WinDivertGetParam(
+ __in HANDLE handle,
+ __in WINDIVERT_PARAM param,
+ __out UINT64 *pValue);
+
+#endif /* WINDIVERT_KERNEL */
+
+/*
+ * WinDivert constants.
+ */
+#define WINDIVERT_PRIORITY_HIGHEST 30000
+#define WINDIVERT_PRIORITY_LOWEST (-WINDIVERT_PRIORITY_HIGHEST)
+#define WINDIVERT_PARAM_QUEUE_LENGTH_DEFAULT 4096
+#define WINDIVERT_PARAM_QUEUE_LENGTH_MIN 32
+#define WINDIVERT_PARAM_QUEUE_LENGTH_MAX 16384
+#define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 2000 /* 2s */
+#define WINDIVERT_PARAM_QUEUE_TIME_MIN 100 /* 100ms */
+#define WINDIVERT_PARAM_QUEUE_TIME_MAX 16000 /* 16s */
+#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 /* 4MB */
+#define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 /* 64KB */
+#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 /* 32MB */
+#define WINDIVERT_BATCH_MAX 0xFF /* 255 */
+#define WINDIVERT_MTU_MAX (40 + 0xFFFF)
+
+/****************************************************************************/
+/* WINDIVERT HELPER API */
+/****************************************************************************/
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable: 4214)
+#endif
+
+/*
+ * IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions.
+ */
+typedef struct
+{
+ UINT8 HdrLength:4;
+ UINT8 Version:4;
+ UINT8 TOS;
+ UINT16 Length;
+ UINT16 Id;
+ UINT16 FragOff0;
+ UINT8 TTL;
+ UINT8 Protocol;
+ UINT16 Checksum;
+ UINT32 SrcAddr;
+ UINT32 DstAddr;
+} WINDIVERT_IPHDR, *PWINDIVERT_IPHDR;
+
+#define WINDIVERT_IPHDR_GET_FRAGOFF(hdr) \
+ (((hdr)->FragOff0) & 0xFF1F)
+#define WINDIVERT_IPHDR_GET_MF(hdr) \
+ ((((hdr)->FragOff0) & 0x0020) != 0)
+#define WINDIVERT_IPHDR_GET_DF(hdr) \
+ ((((hdr)->FragOff0) & 0x0040) != 0)
+#define WINDIVERT_IPHDR_GET_RESERVED(hdr) \
+ ((((hdr)->FragOff0) & 0x0080) != 0)
+
+#define WINDIVERT_IPHDR_SET_FRAGOFF(hdr, val) \
+ do \
+ { \
+ (hdr)->FragOff0 = (((hdr)->FragOff0) & 0x00E0) | \
+ ((val) & 0xFF1F); \
+ } \
+ while (FALSE)
+#define WINDIVERT_IPHDR_SET_MF(hdr, val) \
+ do \
+ { \
+ (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFDF) | \
+ (((val) & 0x0001) << 5); \
+ } \
+ while (FALSE)
+#define WINDIVERT_IPHDR_SET_DF(hdr, val) \
+ do \
+ { \
+ (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFBF) | \
+ (((val) & 0x0001) << 6); \
+ } \
+ while (FALSE)
+#define WINDIVERT_IPHDR_SET_RESERVED(hdr, val) \
+ do \
+ { \
+ (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFF7F) | \
+ (((val) & 0x0001) << 7); \
+ } \
+ while (FALSE)
+
+typedef struct
+{
+ UINT8 TrafficClass0:4;
+ UINT8 Version:4;
+ UINT8 FlowLabel0:4;
+ UINT8 TrafficClass1:4;
+ UINT16 FlowLabel1;
+ UINT16 Length;
+ UINT8 NextHdr;
+ UINT8 HopLimit;
+ UINT32 SrcAddr[4];
+ UINT32 DstAddr[4];
+} WINDIVERT_IPV6HDR, *PWINDIVERT_IPV6HDR;
+
+#define WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(hdr) \
+ ((((hdr)->TrafficClass0) << 4) | ((hdr)->TrafficClass1))
+#define WINDIVERT_IPV6HDR_GET_FLOWLABEL(hdr) \
+ ((((UINT32)(hdr)->FlowLabel0) << 16) | ((UINT32)(hdr)->FlowLabel1))
+
+#define WINDIVERT_IPV6HDR_SET_TRAFFICCLASS(hdr, val) \
+ do \
+ { \
+ (hdr)->TrafficClass0 = ((UINT8)(val) >> 4); \
+ (hdr)->TrafficClass1 = (UINT8)(val); \
+ } \
+ while (FALSE)
+#define WINDIVERT_IPV6HDR_SET_FLOWLABEL(hdr, val) \
+ do \
+ { \
+ (hdr)->FlowLabel0 = (UINT8)((val) >> 16); \
+ (hdr)->FlowLabel1 = (UINT16)(val); \
+ } \
+ while (FALSE)
+
+typedef struct
+{
+ UINT8 Type;
+ UINT8 Code;
+ UINT16 Checksum;
+ UINT32 Body;
+} WINDIVERT_ICMPHDR, *PWINDIVERT_ICMPHDR;
+
+typedef struct
+{
+ UINT8 Type;
+ UINT8 Code;
+ UINT16 Checksum;
+ UINT32 Body;
+} WINDIVERT_ICMPV6HDR, *PWINDIVERT_ICMPV6HDR;
+
+typedef struct
+{
+ UINT16 SrcPort;
+ UINT16 DstPort;
+ UINT32 SeqNum;
+ UINT32 AckNum;
+ UINT16 Reserved1:4;
+ UINT16 HdrLength:4;
+ UINT16 Fin:1;
+ UINT16 Syn:1;
+ UINT16 Rst:1;
+ UINT16 Psh:1;
+ UINT16 Ack:1;
+ UINT16 Urg:1;
+ UINT16 Reserved2:2;
+ UINT16 Window;
+ UINT16 Checksum;
+ UINT16 UrgPtr;
+} WINDIVERT_TCPHDR, *PWINDIVERT_TCPHDR;
+
+typedef struct
+{
+ UINT16 SrcPort;
+ UINT16 DstPort;
+ UINT16 Length;
+ UINT16 Checksum;
+} WINDIVERT_UDPHDR, *PWINDIVERT_UDPHDR;
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+/*
+ * Flags for WinDivertHelperCalcChecksums()
+ */
+#define WINDIVERT_HELPER_NO_IP_CHECKSUM 1
+#define WINDIVERT_HELPER_NO_ICMP_CHECKSUM 2
+#define WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM 4
+#define WINDIVERT_HELPER_NO_TCP_CHECKSUM 8
+#define WINDIVERT_HELPER_NO_UDP_CHECKSUM 16
+
+#ifndef WINDIVERT_KERNEL
+
+/*
+ * Hash a packet.
+ */
+WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket(
+ __in const VOID *pPacket,
+ __in UINT packetLen,
+ __in UINT64 seed
+#ifdef __cplusplus
+ = 0
+#endif
+);
+
+/*
+ * Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
+ __in const VOID *pPacket,
+ __in UINT packetLen,
+ __out_opt PWINDIVERT_IPHDR *ppIpHdr,
+ __out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
+ __out_opt UINT8 *pProtocol,
+ __out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr,
+ __out_opt PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
+ __out_opt PWINDIVERT_TCPHDR *ppTcpHdr,
+ __out_opt PWINDIVERT_UDPHDR *ppUdpHdr,
+ __out_opt PVOID *ppData,
+ __out_opt UINT *pDataLen,
+ __out_opt PVOID *ppNext,
+ __out_opt UINT *pNextLen);
+
+/*
+ * Parse an IPv4 address.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperParseIPv4Address(
+ __in const char *addrStr,
+ __out_opt UINT32 *pAddr);
+
+/*
+ * Parse an IPv6 address.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperParseIPv6Address(
+ __in const char *addrStr,
+ __out_opt UINT32 *pAddr);
+
+/*
+ * Format an IPv4 address.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv4Address(
+ __in UINT32 addr,
+ __out char *buffer,
+ __in UINT bufLen);
+
+/*
+ * Format an IPv6 address.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address(
+ __in const UINT32 *pAddr,
+ __out char *buffer,
+ __in UINT bufLen);
+
+/*
+ * Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperCalcChecksums(
+ __inout VOID *pPacket,
+ __in UINT packetLen,
+ __out_opt WINDIVERT_ADDRESS *pAddr,
+ __in UINT64 flags);
+
+/*
+ * Decrement the TTL/HopLimit.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperDecrementTTL(
+ __inout VOID *pPacket,
+ __in UINT packetLen);
+
+/*
+ * Compile the given filter string.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperCompileFilter(
+ __in const char *filter,
+ __in WINDIVERT_LAYER layer,
+ __out_opt char *object,
+ __in UINT objLen,
+ __out_opt const char **errorStr,
+ __out_opt UINT *errorPos);
+
+/*
+ * Evaluate the given filter string.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter(
+ __in const char *filter,
+ __in const VOID *pPacket,
+ __in UINT packetLen,
+ __in const WINDIVERT_ADDRESS *pAddr);
+
+/*
+ * Format the given filter string.
+ */
+WINDIVERTEXPORT BOOL WinDivertHelperFormatFilter(
+ __in const char *filter,
+ __in WINDIVERT_LAYER layer,
+ __out char *buffer,
+ __in UINT bufLen);
+
+/*
+ * Byte ordering.
+ */
+WINDIVERTEXPORT UINT16 WinDivertHelperNtohs(
+ __in UINT16 x);
+WINDIVERTEXPORT UINT16 WinDivertHelperHtons(
+ __in UINT16 x);
+WINDIVERTEXPORT UINT32 WinDivertHelperNtohl(
+ __in UINT32 x);
+WINDIVERTEXPORT UINT32 WinDivertHelperHtonl(
+ __in UINT32 x);
+WINDIVERTEXPORT UINT64 WinDivertHelperNtohll(
+ __in UINT64 x);
+WINDIVERTEXPORT UINT64 WinDivertHelperHtonll(
+ __in UINT64 x);
+WINDIVERTEXPORT void WinDivertHelperNtohIPv6Address(
+ __in const UINT *inAddr,
+ __out UINT *outAddr);
+WINDIVERTEXPORT void WinDivertHelperHtonIPv6Address(
+ __in const UINT *inAddr,
+ __out UINT *outAddr);
+
+/*
+ * Old names to be removed in the next version.
+ */
+WINDIVERTEXPORT void WinDivertHelperNtohIpv6Address(
+ __in const UINT *inAddr,
+ __out UINT *outAddr);
+WINDIVERTEXPORT void WinDivertHelperHtonIpv6Address(
+ __in const UINT *inAddr,
+ __out UINT *outAddr);
+
+#endif /* WINDIVERT_KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WINDIVERT_H */
diff --git a/NetTunnelSDK/WinDivert/x86/WinDivert.dll b/NetTunnelSDK/WinDivert/x86/WinDivert.dll
new file mode 100644
index 0000000..b9602c0
Binary files /dev/null and b/NetTunnelSDK/WinDivert/x86/WinDivert.dll differ
diff --git a/NetTunnelSDK/WinDivert/x86/WinDivert.lib b/NetTunnelSDK/WinDivert/x86/WinDivert.lib
new file mode 100644
index 0000000..1ec1139
Binary files /dev/null and b/NetTunnelSDK/WinDivert/x86/WinDivert.lib differ
diff --git a/NetTunnelSDK/WinDivert/x86/WinDivert32.sys b/NetTunnelSDK/WinDivert/x86/WinDivert32.sys
new file mode 100644
index 0000000..d06738c
Binary files /dev/null and b/NetTunnelSDK/WinDivert/x86/WinDivert32.sys differ
diff --git a/NetTunnelSDK/WinDivert/x86/WinDivert64.sys b/NetTunnelSDK/WinDivert/x86/WinDivert64.sys
new file mode 100644
index 0000000..218ccaf
Binary files /dev/null and b/NetTunnelSDK/WinDivert/x86/WinDivert64.sys differ
diff --git a/NetTunnelSDK/dllmain.cpp b/NetTunnelSDK/dllmain.cpp
index 08d5d62..cdc86ee 100644
--- a/NetTunnelSDK/dllmain.cpp
+++ b/NetTunnelSDK/dllmain.cpp
@@ -19,8 +19,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserv
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- TunnelSDKUnInit();
+ case DLL_PROCESS_DETACH:
CoFreeUnusedLibraries();
break;
default:
diff --git a/NetTunnelSDK/globalcfg.h b/NetTunnelSDK/globalcfg.h
index f2f571d..7f4fe1b 100644
--- a/NetTunnelSDK/globalcfg.h
+++ b/NetTunnelSDK/globalcfg.h
@@ -74,6 +74,7 @@ typedef struct {
TCHAR systemDirectory[MAX_PATH]; ///< 操作系统目录
TCHAR workDirectory[MAX_PATH]; ///< SDK 当前工作目录
bool isWorkServer; ///< SDK 当前模式 客户端/服务端
+ bool usedSCGProxy; ///< 是否启动 SCG 代理
PROTO_CRYPTO_TYPE proCryptoType; ///< 协议加密类型
TCHAR proKeyBuf[256]; ///< 协议加密秘钥
BOOL enableLog; ///< 是否启用日志
@@ -83,6 +84,7 @@ typedef struct {
WGINTERFACE_CFG wgServerCfg; ///< wireguard 服务端网络接口配置
WGINTERFACE_CFG wgClientCfg; ///< wireguard 客户端网络接口配置
USER_CONFIG userCfg; ///< 用户配置项
+ int curConnVmId; ///< 当前连接的VM
} SDK_CONFIG, *PSDK_CONFIG;
#ifdef __cplusplus // If used by C++ code,
diff --git a/NetTunnelSDK/httplib.h b/NetTunnelSDK/httplib.h
index 9753439..bfa8b56 100644
--- a/NetTunnelSDK/httplib.h
+++ b/NetTunnelSDK/httplib.h
@@ -95,10 +95,8 @@
#endif
#ifndef CPPHTTPLIB_THREAD_POOL_COUNT
-#define CPPHTTPLIB_THREAD_POOL_COUNT \
- ((std::max)(8u, std::thread::hardware_concurrency() > 0 \
- ? std::thread::hardware_concurrency() - 1 \
- : 0))
+#define CPPHTTPLIB_THREAD_POOL_COUNT \
+ ((std::max)(8u, std::thread::hardware_concurrency() > 0 ? std::thread::hardware_concurrency() - 1 : 0))
#endif
#ifndef CPPHTTPLIB_RECV_FLAGS
@@ -120,11 +118,11 @@
#ifdef _WIN32
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
-#endif //_CRT_SECURE_NO_WARNINGS
+#endif //_CRT_SECURE_NO_WARNINGS
#ifndef _CRT_NONSTDC_NO_DEPRECATE
#define _CRT_NONSTDC_NO_DEPRECATE
-#endif //_CRT_NONSTDC_NO_DEPRECATE
+#endif //_CRT_NONSTDC_NO_DEPRECATE
#if defined(_MSC_VER)
#if _MSC_VER < 1900
@@ -138,19 +136,19 @@ using ssize_t = __int64;
#else
using ssize_t = long;
#endif
-#endif // _MSC_VER
+#endif // _MSC_VER
#ifndef S_ISREG
#define S_ISREG(m) (((m)&S_IFREG) == S_IFREG)
-#endif // S_ISREG
+#endif // S_ISREG
#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFDIR) == S_IFDIR)
-#endif // S_ISDIR
+#endif // S_ISDIR
#ifndef NOMINMAX
#define NOMINMAX
-#endif // NOMINMAX
+#endif // NOMINMAX
#include
#include
@@ -162,14 +160,14 @@ using ssize_t = long;
#ifndef strcasecmp
#define strcasecmp _stricmp
-#endif // strcasecmp
+#endif // strcasecmp
using socket_t = SOCKET;
#ifdef CPPHTTPLIB_USE_POLL
#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
#endif
-#else // not _WIN32
+#else // not _WIN32
#include
#if !defined(_AIX) && !defined(__MVS__)
@@ -202,7 +200,7 @@ using socket_t = int;
#ifndef INVALID_SOCKET
#define INVALID_SOCKET (-1)
#endif
-#endif //_WIN32
+#endif //_WIN32
#include
#include
@@ -253,8 +251,8 @@ using socket_t = int;
#if TARGET_OS_OSX
#include
#include
-#endif // TARGET_OS_OSX
-#endif // _WIN32
+#endif // TARGET_OS_OSX
+#endif // _WIN32
#include
#include
@@ -292,6 +290,8 @@ namespace httplib {
namespace detail {
+typedef void (*POSTSOCKETCONNECTCB)(socket_t sock);
+
/*
* Backport std::make_unique from C++14.
*
@@ -300,63 +300,66 @@ namespace detail {
*
*/
-template
-typename std::enable_if::value, std::unique_ptr>::type
-make_unique(Args &&...args) {
- return std::unique_ptr(new T(std::forward(args)...));
+template
+typename std::enable_if::value, std::unique_ptr>::type make_unique(Args &&...args) {
+ return std::unique_ptr(new T(std::forward(args)...));
}
-template
-typename std::enable_if::value, std::unique_ptr>::type
-make_unique(std::size_t n) {
- typedef typename std::remove_extent::type RT;
- return std::unique_ptr(new RT[n]);
+template
+typename std::enable_if::value, std::unique_ptr>::type make_unique(std::size_t n) {
+ typedef typename std::remove_extent::type RT;
+ return std::unique_ptr(new RT[n]);
}
struct ci {
- bool operator()(const std::string &s1, const std::string &s2) const {
- return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(),
- s2.end(),
- [](unsigned char c1, unsigned char c2) {
- return ::tolower(c1) < ::tolower(c2);
- });
- }
+ bool operator()(const std::string &s1, const std::string &s2) const {
+ return std::lexicographical_compare(
+ s1.begin(),
+ s1.end(),
+ s2.begin(),
+ s2.end(),
+ [](unsigned char c1, unsigned char c2) { return ::tolower(c1) < ::tolower(c2); });
+ }
};
// This is based on
// "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189".
struct scope_exit {
- explicit scope_exit(std::function &&f)
- : exit_function(std::move(f)), execute_on_destruction{true} {}
+ explicit scope_exit(std::function &&f) : exit_function(std::move(f)), execute_on_destruction {true} {
+ }
- scope_exit(scope_exit &&rhs)
- : exit_function(std::move(rhs.exit_function)),
- execute_on_destruction{rhs.execute_on_destruction} {
- rhs.release();
- }
+ scope_exit(scope_exit &&rhs)
+ : exit_function(std::move(rhs.exit_function)),
+ execute_on_destruction {rhs.execute_on_destruction} {
+ rhs.release();
+ }
- ~scope_exit() {
- if (execute_on_destruction) { this->exit_function(); }
- }
+ ~scope_exit() {
+ if (execute_on_destruction) {
+ this->exit_function();
+ }
+ }
- void release() { this->execute_on_destruction = false; }
+ void release() {
+ this->execute_on_destruction = false;
+ }
private:
- scope_exit(const scope_exit &) = delete;
- void operator=(const scope_exit &) = delete;
- scope_exit &operator=(scope_exit &&) = delete;
+ scope_exit(const scope_exit &) = delete;
+ void operator=(const scope_exit &) = delete;
+ scope_exit &operator=(scope_exit &&) = delete;
- std::function exit_function;
- bool execute_on_destruction;
+ std::function exit_function;
+ bool execute_on_destruction;
};
-} // namespace detail
+} // namespace detail
using Headers = std::multimap;
using Params = std::multimap;
-using Match = std::smatch;
+using Match = std::smatch;
using Progress = std::function;
@@ -364,302 +367,302 @@ struct Response;
using ResponseHandler = std::function;
struct MultipartFormData {
- std::string name;
- std::string content;
- std::string filename;
- std::string content_type;
+ std::string name;
+ std::string content;
+ std::string filename;
+ std::string content_type;
};
+
using MultipartFormDataItems = std::vector;
-using MultipartFormDataMap = std::multimap;
+using MultipartFormDataMap = std::multimap;
class DataSink {
public:
- DataSink() : os(&sb_), sb_(*this) {}
-
- DataSink(const DataSink &) = delete;
- DataSink &operator=(const DataSink &) = delete;
- DataSink(DataSink &&) = delete;
- DataSink &operator=(DataSink &&) = delete;
-
- std::function write;
- std::function done;
- std::function done_with_trailer;
- std::ostream os;
-
-private:
- class data_sink_streambuf : public std::streambuf {
- public:
- explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {}
-
- protected:
- std::streamsize xsputn(const char *s, std::streamsize n) {
- sink_.write(s, static_cast(n));
- return n;
+ DataSink() : os(&sb_), sb_(*this) {
}
- private:
- DataSink &sink_;
- };
+ DataSink(const DataSink &) = delete;
+ DataSink &operator=(const DataSink &) = delete;
+ DataSink(DataSink &&) = delete;
+ DataSink &operator=(DataSink &&) = delete;
- data_sink_streambuf sb_;
+ std::function write;
+ std::function done;
+ std::function done_with_trailer;
+ std::ostream os;
+
+private:
+ class data_sink_streambuf : public std::streambuf {
+ public:
+ explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {
+ }
+
+ protected:
+ std::streamsize xsputn(const char *s, std::streamsize n) {
+ sink_.write(s, static_cast(n));
+ return n;
+ }
+
+ private:
+ DataSink &sink_;
+ };
+
+ data_sink_streambuf sb_;
};
-using ContentProvider =
- std::function;
+using ContentProvider = std::function;
-using ContentProviderWithoutLength =
- std::function;
+using ContentProviderWithoutLength = std::function;
using ContentProviderResourceReleaser = std::function;
struct MultipartFormDataProvider {
- std::string name;
- ContentProviderWithoutLength provider;
- std::string filename;
- std::string content_type;
+ std::string name;
+ ContentProviderWithoutLength provider;
+ std::string filename;
+ std::string content_type;
};
+
using MultipartFormDataProviderItems = std::vector;
-using ContentReceiverWithProgress =
- std::function;
+using ContentReceiverWithProgress = std::function<
+ bool(const char *data, size_t data_length, uint64_t offset, uint64_t total_length)>;
-using ContentReceiver =
- std::function;
+using ContentReceiver = std::function;
-using MultipartContentHeader =
- std::function;
+using MultipartContentHeader = std::function;
class ContentReader {
public:
- using Reader = std::function;
- using MultipartReader = std::function;
+ using Reader = std::function;
+ using MultipartReader = std::function;
- ContentReader(Reader reader, MultipartReader multipart_reader)
- : reader_(std::move(reader)),
- multipart_reader_(std::move(multipart_reader)) {}
+ ContentReader(Reader reader, MultipartReader multipart_reader)
+ : reader_(std::move(reader)),
+ multipart_reader_(std::move(multipart_reader)) {
+ }
- bool operator()(MultipartContentHeader header,
- ContentReceiver receiver) const {
- return multipart_reader_(std::move(header), std::move(receiver));
- }
+ bool operator()(MultipartContentHeader header, ContentReceiver receiver) const {
+ return multipart_reader_(std::move(header), std::move(receiver));
+ }
- bool operator()(ContentReceiver receiver) const {
- return reader_(std::move(receiver));
- }
+ bool operator()(ContentReceiver receiver) const {
+ return reader_(std::move(receiver));
+ }
- Reader reader_;
- MultipartReader multipart_reader_;
+ Reader reader_;
+ MultipartReader multipart_reader_;
};
-using Range = std::pair;
+using Range = std::pair;
using Ranges = std::vector;
struct Request {
- std::string method;
- std::string path;
- Headers headers;
- std::string body;
+ std::string method;
+ std::string path;
+ Headers headers;
+ std::string body;
- std::string remote_addr;
- int remote_port = -1;
- std::string local_addr;
- int local_port = -1;
+ std::string remote_addr;
+ int remote_port = -1;
+ std::string local_addr;
+ int local_port = -1;
- // for server
- std::string version;
- std::string target;
- Params params;
- MultipartFormDataMap files;
- Ranges ranges;
- Match matches;
- std::unordered_map path_params;
+ // for server
+ std::string version;
+ std::string target;
+ Params params;
+ MultipartFormDataMap files;
+ Ranges ranges;
+ Match matches;
+ std::unordered_map path_params;
- // for client
- ResponseHandler response_handler;
- ContentReceiverWithProgress content_receiver;
- Progress progress;
+ // for client
+ ResponseHandler response_handler;
+ ContentReceiverWithProgress content_receiver;
+ Progress progress;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- const SSL *ssl = nullptr;
+ const SSL *ssl = nullptr;
#endif
- bool has_header(const std::string &key) const;
- std::string get_header_value(const std::string &key, size_t id = 0) const;
- template
- T get_header_value(const std::string &key, size_t id = 0) const;
- size_t get_header_value_count(const std::string &key) const;
- void set_header(const std::string &key, const std::string &val);
+ bool has_header(const std::string &key) const;
+ std::string get_header_value(const std::string &key, size_t id = 0) const;
+ template T get_header_value(const std::string &key, size_t id = 0) const;
+ size_t get_header_value_count(const std::string &key) const;
+ void set_header(const std::string &key, const std::string &val);
- bool has_param(const std::string &key) const;
- std::string get_param_value(const std::string &key, size_t id = 0) const;
- size_t get_param_value_count(const std::string &key) const;
+ bool has_param(const std::string &key) const;
+ std::string get_param_value(const std::string &key, size_t id = 0) const;
+ size_t get_param_value_count(const std::string &key) const;
- bool is_multipart_form_data() const;
+ bool is_multipart_form_data() const;
- bool has_file(const std::string &key) const;
- MultipartFormData get_file_value(const std::string &key) const;
- std::vector get_file_values(const std::string &key) const;
+ bool has_file(const std::string &key) const;
+ MultipartFormData get_file_value(const std::string &key) const;
+ std::vector get_file_values(const std::string &key) const;
- // private members...
- size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT;
- size_t content_length_ = 0;
- ContentProvider content_provider_;
- bool is_chunked_content_provider_ = false;
- size_t authorization_count_ = 0;
+ // private members...
+ size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT;
+ size_t content_length_ = 0;
+ ContentProvider content_provider_;
+ bool is_chunked_content_provider_ = false;
+ size_t authorization_count_ = 0;
};
struct Response {
- std::string version;
- int status = -1;
- std::string reason;
- Headers headers;
- std::string body;
- std::string location; // Redirect location
+ std::string version;
+ int status = -1;
+ std::string reason;
+ Headers headers;
+ std::string body;
+ std::string location; // Redirect location
- bool has_header(const std::string &key) const;
- std::string get_header_value(const std::string &key, size_t id = 0) const;
- template
- T get_header_value(const std::string &key, size_t id = 0) const;
- size_t get_header_value_count(const std::string &key) const;
- void set_header(const std::string &key, const std::string &val);
+ bool has_header(const std::string &key) const;
+ std::string get_header_value(const std::string &key, size_t id = 0) const;
+ template T get_header_value(const std::string &key, size_t id = 0) const;
+ size_t get_header_value_count(const std::string &key) const;
+ void set_header(const std::string &key, const std::string &val);
- void set_redirect(const std::string &url, int status = 302);
- void set_content(const char *s, size_t n, const std::string &content_type);
- void set_content(const std::string &s, const std::string &content_type);
+ void set_redirect(const std::string &url, int status = 302);
+ void set_content(const char *s, size_t n, const std::string &content_type);
+ void set_content(const std::string &s, const std::string &content_type);
- void set_content_provider(
- size_t length, const std::string &content_type, ContentProvider provider,
- ContentProviderResourceReleaser resource_releaser = nullptr);
+ void set_content_provider(size_t length,
+ const std::string &content_type,
+ ContentProvider provider,
+ ContentProviderResourceReleaser resource_releaser = nullptr);
- void set_content_provider(
- const std::string &content_type, ContentProviderWithoutLength provider,
- ContentProviderResourceReleaser resource_releaser = nullptr);
+ void set_content_provider(const std::string &content_type,
+ ContentProviderWithoutLength provider,
+ ContentProviderResourceReleaser resource_releaser = nullptr);
- void set_chunked_content_provider(
- const std::string &content_type, ContentProviderWithoutLength provider,
- ContentProviderResourceReleaser resource_releaser = nullptr);
+ void set_chunked_content_provider(const std::string &content_type,
+ ContentProviderWithoutLength provider,
+ ContentProviderResourceReleaser resource_releaser = nullptr);
- Response() = default;
- Response(const Response &) = default;
- Response &operator=(const Response &) = default;
- Response(Response &&) = default;
- Response &operator=(Response &&) = default;
- ~Response() {
- if (content_provider_resource_releaser_) {
- content_provider_resource_releaser_(content_provider_success_);
+ Response() = default;
+ Response(const Response &) = default;
+ Response &operator=(const Response &) = default;
+ Response(Response &&) = default;
+ Response &operator=(Response &&) = default;
+
+ ~Response() {
+ if (content_provider_resource_releaser_) {
+ content_provider_resource_releaser_(content_provider_success_);
+ }
}
- }
- // private members...
- size_t content_length_ = 0;
- ContentProvider content_provider_;
- ContentProviderResourceReleaser content_provider_resource_releaser_;
- bool is_chunked_content_provider_ = false;
- bool content_provider_success_ = false;
+ // private members...
+ size_t content_length_ = 0;
+ ContentProvider content_provider_;
+ ContentProviderResourceReleaser content_provider_resource_releaser_;
+ bool is_chunked_content_provider_ = false;
+ bool content_provider_success_ = false;
};
class Stream {
public:
- virtual ~Stream() = default;
+ virtual ~Stream() = default;
- virtual bool is_readable() const = 0;
- virtual bool is_writable() const = 0;
+ virtual bool is_readable() const = 0;
+ virtual bool is_writable() const = 0;
- virtual ssize_t read(char *ptr, size_t size) = 0;
- virtual ssize_t write(const char *ptr, size_t size) = 0;
- virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0;
- virtual void get_local_ip_and_port(std::string &ip, int &port) const = 0;
- virtual socket_t socket() const = 0;
+ virtual ssize_t read(char *ptr, size_t size) = 0;
+ virtual ssize_t write(const char *ptr, size_t size) = 0;
+ virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0;
+ virtual void get_local_ip_and_port(std::string &ip, int &port) const = 0;
+ virtual socket_t socket() const = 0;
- template
- ssize_t write_format(const char *fmt, const Args &...args);
- ssize_t write(const char *ptr);
- ssize_t write(const std::string &s);
+ template ssize_t write_format(const char *fmt, const Args &...args);
+ ssize_t write(const char *ptr);
+ ssize_t write(const std::string &s);
};
class TaskQueue {
public:
- TaskQueue() = default;
- virtual ~TaskQueue() = default;
+ TaskQueue() = default;
+ virtual ~TaskQueue() = default;
- virtual void enqueue(std::function fn) = 0;
- virtual void shutdown() = 0;
+ virtual void enqueue(std::function fn) = 0;
+ virtual void shutdown() = 0;
- virtual void on_idle() {}
+ virtual void on_idle() {
+ }
};
class ThreadPool : public TaskQueue {
public:
- explicit ThreadPool(size_t n) : shutdown_(false) {
- while (n) {
- threads_.emplace_back(worker(*this));
- n--;
- }
- }
-
- ThreadPool(const ThreadPool &) = delete;
- ~ThreadPool() override = default;
-
- void enqueue(std::function fn) override {
- {
- std::unique_lock lock(mutex_);
- jobs_.push_back(std::move(fn));
+ explicit ThreadPool(size_t n) : shutdown_(false) {
+ while (n) {
+ threads_.emplace_back(worker(*this));
+ n--;
+ }
}
- cond_.notify_one();
- }
+ ThreadPool(const ThreadPool &) = delete;
+ ~ThreadPool() override = default;
- void shutdown() override {
- // Stop all worker threads...
- {
- std::unique_lock lock(mutex_);
- shutdown_ = true;
- }
-
- cond_.notify_all();
-
- // Join...
- for (auto &t : threads_) {
- t.join();
- }
- }
-
-private:
- struct worker {
- explicit worker(ThreadPool &pool) : pool_(pool) {}
-
- void operator()() {
- for (;;) {
- std::function fn;
+ void enqueue(std::function fn) override {
{
- std::unique_lock lock(pool_.mutex_);
-
- pool_.cond_.wait(
- lock, [&] { return !pool_.jobs_.empty() || pool_.shutdown_; });
-
- if (pool_.shutdown_ && pool_.jobs_.empty()) { break; }
-
- fn = std::move(pool_.jobs_.front());
- pool_.jobs_.pop_front();
+ std::unique_lock lock(mutex_);
+ jobs_.push_back(std::move(fn));
}
- assert(true == static_cast(fn));
- fn();
- }
+ cond_.notify_one();
}
- ThreadPool &pool_;
- };
- friend struct worker;
+ void shutdown() override {
+ // Stop all worker threads...
+ {
+ std::unique_lock lock(mutex_);
+ shutdown_ = true;
+ }
- std::vector threads_;
- std::list> jobs_;
+ cond_.notify_all();
- bool shutdown_;
+ // Join...
+ for (auto &t : threads_) {
+ t.join();
+ }
+ }
- std::condition_variable cond_;
- std::mutex mutex_;
+private:
+ struct worker {
+ explicit worker(ThreadPool &pool) : pool_(pool) {
+ }
+
+ void operator()() {
+ for (;;) {
+ std::function fn;
+ {
+ std::unique_lock lock(pool_.mutex_);
+
+ pool_.cond_.wait(lock, [&] { return !pool_.jobs_.empty() || pool_.shutdown_; });
+
+ if (pool_.shutdown_ && pool_.jobs_.empty()) {
+ break;
+ }
+
+ fn = std::move(pool_.jobs_.front());
+ pool_.jobs_.pop_front();
+ }
+
+ assert(true == static_cast(fn));
+ fn();
+ }
+ }
+
+ ThreadPool &pool_;
+ };
+ friend struct worker;
+
+ std::vector threads_;
+ std::list> jobs_;
+
+ bool shutdown_;
+
+ std::condition_variable cond_;
+ std::mutex mutex_;
};
using Logger = std::function;
@@ -672,10 +675,10 @@ namespace detail {
class MatcherBase {
public:
- virtual ~MatcherBase() = default;
+ virtual ~MatcherBase() = default;
- // Match request path and populate its matches and
- virtual bool match(Request &request) const = 0;
+ // Match request path and populate its matches and
+ virtual bool match(Request &request) const = 0;
};
/**
@@ -698,24 +701,24 @@ public:
*/
class PathParamsMatcher : public MatcherBase {
public:
- PathParamsMatcher(const std::string &pattern);
+ PathParamsMatcher(const std::string &pattern);
- bool match(Request &request) const override;
+ bool match(Request &request) const override;
private:
- static constexpr char marker = ':';
- // Treat segment separators as the end of path parameter capture
- // Does not need to handle query parameters as they are parsed before path
- // matching
- static constexpr char separator = '/';
+ static constexpr char marker = ':';
+ // Treat segment separators as the end of path parameter capture
+ // Does not need to handle query parameters as they are parsed before path
+ // matching
+ static constexpr char separator = '/';
- // Contains static path fragments to match against, excluding the '/' after
- // path params
- // Fragments are separated by path params
- std::vector static_fragments_;
- // Stores the names of the path parameters to be used as keys in the
- // Request::path_params map
- std::vector param_names_;
+ // Contains static path fragments to match against, excluding the '/' after
+ // path params
+ // Fragments are separated by path params
+ std::vector static_fragments_;
+ // Stores the names of the path parameters to be used as keys in the
+ // Request::path_params map
+ std::vector param_names_;
};
/**
@@ -728,229 +731,224 @@ private:
*/
class RegexMatcher : public MatcherBase {
public:
- RegexMatcher(const std::string &pattern) : regex_(pattern) {}
+ RegexMatcher(const std::string &pattern) : regex_(pattern) {
+ }
- bool match(Request &request) const override;
+ bool match(Request &request) const override;
private:
- std::regex regex_;
+ std::regex regex_;
};
-} // namespace detail
+} // namespace detail
class Server {
public:
- using Handler = std::function;
+ using Handler = std::function;
- using ExceptionHandler =
- std::function;
+ using ExceptionHandler = std::function;
- enum class HandlerResponse {
- Handled,
- Unhandled,
- };
- using HandlerWithResponse =
- std::function;
+ enum class HandlerResponse {
+ Handled,
+ Unhandled,
+ };
+ using HandlerWithResponse = std::function;
- using HandlerWithContentReader = std::function;
+ using HandlerWithContentReader = std::function<
+ void(const Request &, Response &, const ContentReader &content_reader)>;
- using Expect100ContinueHandler =
- std::function;
+ using Expect100ContinueHandler = std::function;
- Server();
+ Server();
- virtual ~Server();
+ virtual ~Server();
- virtual bool is_valid() const;
+ virtual bool is_valid() const;
- Server &Get(const std::string &pattern, Handler handler);
- Server &Post(const std::string &pattern, Handler handler);
- Server &Post(const std::string &pattern, HandlerWithContentReader handler);
- Server &Put(const std::string &pattern, Handler handler);
- Server &Put(const std::string &pattern, HandlerWithContentReader handler);
- Server &Patch(const std::string &pattern, Handler handler);
- Server &Patch(const std::string &pattern, HandlerWithContentReader handler);
- Server &Delete(const std::string &pattern, Handler handler);
- Server &Delete(const std::string &pattern, HandlerWithContentReader handler);
- Server &Options(const std::string &pattern, Handler handler);
+ Server &Get(const std::string &pattern, Handler handler);
+ Server &Post(const std::string &pattern, Handler handler);
+ Server &Post(const std::string &pattern, HandlerWithContentReader handler);
+ Server &Put(const std::string &pattern, Handler handler);
+ Server &Put(const std::string &pattern, HandlerWithContentReader handler);
+ Server &Patch(const std::string &pattern, Handler handler);
+ Server &Patch(const std::string &pattern, HandlerWithContentReader handler);
+ Server &Delete(const std::string &pattern, Handler handler);
+ Server &Delete(const std::string &pattern, HandlerWithContentReader handler);
+ Server &Options(const std::string &pattern, Handler handler);
- bool set_base_dir(const std::string &dir,
- const std::string &mount_point = std::string());
- bool set_mount_point(const std::string &mount_point, const std::string &dir,
- Headers headers = Headers());
- bool remove_mount_point(const std::string &mount_point);
- Server &set_file_extension_and_mimetype_mapping(const std::string &ext,
- const std::string &mime);
- Server &set_file_request_handler(Handler handler);
+ bool set_base_dir(const std::string &dir, const std::string &mount_point = std::string());
+ bool set_mount_point(const std::string &mount_point, const std::string &dir, Headers headers = Headers());
+ bool remove_mount_point(const std::string &mount_point);
+ Server &set_file_extension_and_mimetype_mapping(const std::string &ext, const std::string &mime);
+ Server &set_file_request_handler(Handler handler);
- Server &set_error_handler(HandlerWithResponse handler);
- Server &set_error_handler(Handler handler);
- Server &set_exception_handler(ExceptionHandler handler);
- Server &set_pre_routing_handler(HandlerWithResponse handler);
- Server &set_post_routing_handler(Handler handler);
+ Server &set_error_handler(HandlerWithResponse handler);
+ Server &set_error_handler(Handler handler);
+ Server &set_exception_handler(ExceptionHandler handler);
+ Server &set_pre_routing_handler(HandlerWithResponse handler);
+ Server &set_post_routing_handler(Handler handler);
- Server &set_expect_100_continue_handler(Expect100ContinueHandler handler);
- Server &set_logger(Logger logger);
+ Server &set_expect_100_continue_handler(Expect100ContinueHandler handler);
+ Server &set_logger(Logger logger);
- Server &set_address_family(int family);
- Server &set_tcp_nodelay(bool on);
- Server &set_socket_options(SocketOptions socket_options);
+ Server &set_address_family(int family);
+ Server &set_tcp_nodelay(bool on);
+ Server &set_socket_options(SocketOptions socket_options);
- Server &set_default_headers(Headers headers);
+ Server &set_default_headers(Headers headers);
- Server &set_keep_alive_max_count(size_t count);
- Server &set_keep_alive_timeout(time_t sec);
+ Server &set_keep_alive_max_count(size_t count);
+ Server &set_keep_alive_timeout(time_t sec);
- Server &set_read_timeout(time_t sec, time_t usec = 0);
- template
- Server &set_read_timeout(const std::chrono::duration &duration);
+ Server &set_read_timeout(time_t sec, time_t usec = 0);
+ template Server &set_read_timeout(const std::chrono::duration &duration);
- Server &set_write_timeout(time_t sec, time_t usec = 0);
- template
- Server &set_write_timeout(const std::chrono::duration &duration);
+ Server &set_write_timeout(time_t sec, time_t usec = 0);
+ template Server &set_write_timeout(const std::chrono::duration &duration);
- Server &set_idle_interval(time_t sec, time_t usec = 0);
- template
- Server &set_idle_interval(const std::chrono::duration &duration);
+ Server &set_idle_interval(time_t sec, time_t usec = 0);
+ template Server &set_idle_interval(const std::chrono::duration &duration);
- Server &set_payload_max_length(size_t length);
+ Server &set_payload_max_length(size_t length);
- bool bind_to_port(const std::string &host, int port, int socket_flags = 0);
- int bind_to_any_port(const std::string &host, int socket_flags = 0);
- bool listen_after_bind();
+ bool bind_to_port(const std::string &host, int port, int socket_flags = 0);
+ int bind_to_any_port(const std::string &host, int socket_flags = 0);
+ bool listen_after_bind();
- bool listen(const std::string &host, int port, int socket_flags = 0);
+ bool listen(const std::string &host, int port, int socket_flags = 0);
- bool is_running() const;
- void wait_until_ready() const;
- void stop();
+ bool is_running() const;
+ void wait_until_ready() const;
+ void stop();
- std::function new_task_queue;
+ std::function new_task_queue;
protected:
- bool process_request(Stream &strm, bool close_connection,
- bool &connection_closed,
- const std::function &setup_request);
+ bool process_request(Stream &strm,
+ bool close_connection,
+ bool &connection_closed,
+ const std::function &setup_request);
- std::atomic svr_sock_{INVALID_SOCKET};
- size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
- time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
- time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
- time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
- time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
- time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
- time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND;
- time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND;
- size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH;
+ std::atomic svr_sock_ {INVALID_SOCKET};
+ size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
+ time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
+ time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
+ time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
+ time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
+ time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
+ time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND;
+ time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND;
+ size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH;
private:
- using Handlers =
- std::vector, Handler>>;
- using HandlersForContentReader =
- std::vector,
- HandlerWithContentReader>>;
+ using Handlers = std::vector, Handler>>;
+ using HandlersForContentReader = std::vector<
+ std::pair, HandlerWithContentReader>>;
- static std::unique_ptr
- make_matcher(const std::string &pattern);
+ static std::unique_ptr make_matcher(const std::string &pattern);
- socket_t create_server_socket(const std::string &host, int port,
- int socket_flags,
- SocketOptions socket_options) const;
- int bind_internal(const std::string &host, int port, int socket_flags);
- bool listen_internal();
+ socket_t create_server_socket(const std::string &host,
+ int port,
+ int socket_flags,
+ SocketOptions socket_options) const;
+ int bind_internal(const std::string &host, int port, int socket_flags);
+ bool listen_internal();
- bool routing(Request &req, Response &res, Stream &strm);
- bool handle_file_request(const Request &req, Response &res,
- bool head = false);
- bool dispatch_request(Request &req, Response &res, const Handlers &handlers);
- bool
- dispatch_request_for_content_reader(Request &req, Response &res,
- ContentReader content_reader,
- const HandlersForContentReader &handlers);
+ bool routing(Request &req, Response &res, Stream &strm);
+ bool handle_file_request(const Request &req, Response &res, bool head = false);
+ bool dispatch_request(Request &req, Response &res, const Handlers &handlers);
+ bool dispatch_request_for_content_reader(Request &req,
+ Response &res,
+ ContentReader content_reader,
+ const HandlersForContentReader &handlers);
- bool parse_request_line(const char *s, Request &req);
- void apply_ranges(const Request &req, Response &res,
- std::string &content_type, std::string &boundary);
- bool write_response(Stream &strm, bool close_connection, const Request &req,
- Response &res);
- bool write_response_with_content(Stream &strm, bool close_connection,
- const Request &req, Response &res);
- bool write_response_core(Stream &strm, bool close_connection,
- const Request &req, Response &res,
- bool need_apply_ranges);
- bool write_content_with_provider(Stream &strm, const Request &req,
- Response &res, const std::string &boundary,
- const std::string &content_type);
- bool read_content(Stream &strm, Request &req, Response &res);
- bool
- read_content_with_content_receiver(Stream &strm, Request &req, Response &res,
- ContentReceiver receiver,
- MultipartContentHeader multipart_header,
- ContentReceiver multipart_receiver);
- bool read_content_core(Stream &strm, Request &req, Response &res,
- ContentReceiver receiver,
- MultipartContentHeader multipart_header,
- ContentReceiver multipart_receiver);
+ bool parse_request_line(const char *s, Request &req);
+ void apply_ranges(const Request &req, Response &res, std::string &content_type, std::string &boundary);
+ bool write_response(Stream &strm, bool close_connection, const Request &req, Response &res);
+ bool write_response_with_content(Stream &strm, bool close_connection, const Request &req, Response &res);
+ bool write_response_core(Stream &strm,
+ bool close_connection,
+ const Request &req,
+ Response &res,
+ bool need_apply_ranges);
+ bool write_content_with_provider(Stream &strm,
+ const Request &req,
+ Response &res,
+ const std::string &boundary,
+ const std::string &content_type);
+ bool read_content(Stream &strm, Request &req, Response &res);
+ bool read_content_with_content_receiver(Stream &strm,
+ Request &req,
+ Response &res,
+ ContentReceiver receiver,
+ MultipartContentHeader multipart_header,
+ ContentReceiver multipart_receiver);
+ bool read_content_core(Stream &strm,
+ Request &req,
+ Response &res,
+ ContentReceiver receiver,
+ MultipartContentHeader multipart_header,
+ ContentReceiver multipart_receiver);
- virtual bool process_and_close_socket(socket_t sock);
+ virtual bool process_and_close_socket(socket_t sock);
- std::atomic is_running_{false};
- std::atomic done_{false};
+ std::atomic is_running_ {false};
+ std::atomic done_ {false};
- struct MountPointEntry {
- std::string mount_point;
- std::string base_dir;
- Headers headers;
- };
- std::vector base_dirs_;
- std::map file_extension_and_mimetype_map_;
- Handler file_request_handler_;
+ struct MountPointEntry {
+ std::string mount_point;
+ std::string base_dir;
+ Headers headers;
+ };
- Handlers get_handlers_;
- Handlers post_handlers_;
- HandlersForContentReader post_handlers_for_content_reader_;
- Handlers put_handlers_;
- HandlersForContentReader put_handlers_for_content_reader_;
- Handlers patch_handlers_;
- HandlersForContentReader patch_handlers_for_content_reader_;
- Handlers delete_handlers_;
- HandlersForContentReader delete_handlers_for_content_reader_;
- Handlers options_handlers_;
+ std::vector base_dirs_;
+ std::map file_extension_and_mimetype_map_;
+ Handler file_request_handler_;
- HandlerWithResponse error_handler_;
- ExceptionHandler exception_handler_;
- HandlerWithResponse pre_routing_handler_;
- Handler post_routing_handler_;
- Expect100ContinueHandler expect_100_continue_handler_;
+ Handlers get_handlers_;
+ Handlers post_handlers_;
+ HandlersForContentReader post_handlers_for_content_reader_;
+ Handlers put_handlers_;
+ HandlersForContentReader put_handlers_for_content_reader_;
+ Handlers patch_handlers_;
+ HandlersForContentReader patch_handlers_for_content_reader_;
+ Handlers delete_handlers_;
+ HandlersForContentReader delete_handlers_for_content_reader_;
+ Handlers options_handlers_;
- Logger logger_;
+ HandlerWithResponse error_handler_;
+ ExceptionHandler exception_handler_;
+ HandlerWithResponse pre_routing_handler_;
+ Handler post_routing_handler_;
+ Expect100ContinueHandler expect_100_continue_handler_;
- int address_family_ = AF_UNSPEC;
- bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
- SocketOptions socket_options_ = default_socket_options;
+ Logger logger_;
- Headers default_headers_;
+ int address_family_ = AF_UNSPEC;
+ bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
+ SocketOptions socket_options_ = default_socket_options;
+
+ Headers default_headers_;
};
enum class Error {
- Success = 0,
- Unknown,
- Connection,
- BindIPAddress,
- Read,
- Write,
- ExceedRedirectCount,
- Canceled,
- SSLConnection,
- SSLLoadingCerts,
- SSLServerVerification,
- UnsupportedMultipartBoundaryChars,
- Compression,
- ConnectionTimeout,
+ Success = 0,
+ Unknown,
+ Connection,
+ BindIPAddress,
+ Read,
+ Write,
+ ExceedRedirectCount,
+ Canceled,
+ SSLConnection,
+ SSLLoadingCerts,
+ SSLServerVerification,
+ UnsupportedMultipartBoundaryChars,
+ Compression,
+ ConnectionTimeout,
- // For internal use only
- SSLPeerCouldBeClosed_,
+ // For internal use only
+ SSLPeerCouldBeClosed_,
};
std::string to_string(const Error error);
@@ -959,733 +957,804 @@ std::ostream &operator<<(std::ostream &os, const Error &obj);
class Result {
public:
- Result() = default;
- Result(std::unique_ptr &&res, Error err,
- Headers &&request_headers = Headers{})
- : res_(std::move(res)), err_(err),
- request_headers_(std::move(request_headers)) {}
- // Response
- operator bool() const { return res_ != nullptr; }
- bool operator==(std::nullptr_t) const { return res_ == nullptr; }
- bool operator!=(std::nullptr_t) const { return res_ != nullptr; }
- const Response &value() const { return *res_; }
- Response &value() { return *res_; }
- const Response &operator*() const { return *res_; }
- Response &operator*() { return *res_; }
- const Response *operator->() const { return res_.get(); }
- Response *operator->() { return res_.get(); }
+ Result() = default;
- // Error
- Error error() const { return err_; }
+ Result(std::unique_ptr &&res, Error err, Headers &&request_headers = Headers {})
+ : res_(std::move(res)),
+ err_(err),
+ request_headers_(std::move(request_headers)) {
+ }
- // Request Headers
- bool has_request_header(const std::string &key) const;
- std::string get_request_header_value(const std::string &key,
- size_t id = 0) const;
- template
- T get_request_header_value(const std::string &key, size_t id = 0) const;
- size_t get_request_header_value_count(const std::string &key) const;
+ // Response
+ operator bool() const {
+ return res_ != nullptr;
+ }
+
+ bool operator==(std::nullptr_t) const {
+ return res_ == nullptr;
+ }
+
+ bool operator!=(std::nullptr_t) const {
+ return res_ != nullptr;
+ }
+
+ const Response &value() const {
+ return *res_;
+ }
+
+ Response &value() {
+ return *res_;
+ }
+
+ const Response &operator*() const {
+ return *res_;
+ }
+
+ Response &operator*() {
+ return *res_;
+ }
+
+ const Response *operator->() const {
+ return res_.get();
+ }
+
+ Response *operator->() {
+ return res_.get();
+ }
+
+ // Error
+ Error error() const {
+ return err_;
+ }
+
+ // Request Headers
+ bool has_request_header(const std::string &key) const;
+ std::string get_request_header_value(const std::string &key, size_t id = 0) const;
+ template T get_request_header_value(const std::string &key, size_t id = 0) const;
+ size_t get_request_header_value_count(const std::string &key) const;
private:
- std::unique_ptr res_;
- Error err_ = Error::Unknown;
- Headers request_headers_;
+ std::unique_ptr res_;
+ Error err_ = Error::Unknown;
+ Headers request_headers_;
};
class ClientImpl {
public:
- explicit ClientImpl(const std::string &host);
+ explicit ClientImpl(const std::string &host);
- explicit ClientImpl(const std::string &host, int port);
+ explicit ClientImpl(const std::string &host, int port);
- explicit ClientImpl(const std::string &host, int port,
- const std::string &client_cert_path,
- const std::string &client_key_path);
+ explicit ClientImpl(const std::string &host,
+ int port,
+ const std::string &client_cert_path,
+ const std::string &client_key_path);
- virtual ~ClientImpl();
+ virtual ~ClientImpl();
- virtual bool is_valid() const;
+ virtual bool is_valid() const;
- Result Get(const std::string &path);
- Result Get(const std::string &path, const Headers &headers);
- Result Get(const std::string &path, Progress progress);
- Result Get(const std::string &path, const Headers &headers,
- Progress progress);
- Result Get(const std::string &path, ContentReceiver content_receiver);
- Result Get(const std::string &path, const Headers &headers,
- ContentReceiver content_receiver);
- Result Get(const std::string &path, ContentReceiver content_receiver,
- Progress progress);
- Result Get(const std::string &path, const Headers &headers,
- ContentReceiver content_receiver, Progress progress);
- Result Get(const std::string &path, ResponseHandler response_handler,
- ContentReceiver content_receiver);
- Result Get(const std::string &path, const Headers &headers,
- ResponseHandler response_handler,
- ContentReceiver content_receiver);
- Result Get(const std::string &path, ResponseHandler response_handler,
- ContentReceiver content_receiver, Progress progress);
- Result Get(const std::string &path, const Headers &headers,
- ResponseHandler response_handler, ContentReceiver content_receiver,
- Progress progress);
+ Result Get(const std::string &path);
+ Result Get(const std::string &path, const Headers &headers);
+ Result Get(const std::string &path, Progress progress);
+ Result Get(const std::string &path, const Headers &headers, Progress progress);
+ Result Get(const std::string &path, ContentReceiver content_receiver);
+ Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver);
+ Result Get(const std::string &path, ContentReceiver content_receiver, Progress progress);
+ Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, Progress progress);
+ Result Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver);
+ Result Get(const std::string &path,
+ const Headers &headers,
+ ResponseHandler response_handler,
+ ContentReceiver content_receiver);
+ Result Get(const std::string &path,
+ ResponseHandler response_handler,
+ ContentReceiver content_receiver,
+ Progress progress);
+ Result Get(const std::string &path,
+ const Headers &headers,
+ ResponseHandler response_handler,
+ ContentReceiver content_receiver,
+ Progress progress);
- Result Get(const std::string &path, const Params ¶ms,
- const Headers &headers, Progress progress = nullptr);
- Result Get(const std::string &path, const Params ¶ms,
- const Headers &headers, ContentReceiver content_receiver,
- Progress progress = nullptr);
- Result Get(const std::string &path, const Params ¶ms,
- const Headers &headers, ResponseHandler response_handler,
- ContentReceiver content_receiver, Progress progress = nullptr);
+ Result Get(const std::string &path, const Params ¶ms, const Headers &headers, Progress progress = nullptr);
+ Result Get(const std::string &path,
+ const Params ¶ms,
+ const Headers &headers,
+ ContentReceiver content_receiver,
+ Progress progress = nullptr);
+ Result Get(const std::string &path,
+ const Params ¶ms,
+ const Headers &headers,
+ ResponseHandler response_handler,
+ ContentReceiver content_receiver,
+ Progress progress = nullptr);
- Result Head(const std::string &path);
- Result Head(const std::string &path, const Headers &headers);
+ Result Head(const std::string &path);
+ Result Head(const std::string &path, const Headers &headers);
- Result Post(const std::string &path);
- Result Post(const std::string &path, const Headers &headers);
- Result Post(const std::string &path, const char *body, size_t content_length,
- const std::string &content_type);
- Result Post(const std::string &path, const Headers &headers, const char *body,
- size_t content_length, const std::string &content_type);
- Result Post(const std::string &path, const std::string &body,
- const std::string &content_type);
- Result Post(const std::string &path, const Headers &headers,
- const std::string &body, const std::string &content_type);
- Result Post(const std::string &path, size_t content_length,
- ContentProvider content_provider,
- const std::string &content_type);
- Result Post(const std::string &path,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Post(const std::string &path, const Headers &headers,
- size_t content_length, ContentProvider content_provider,
- const std::string &content_type);
- Result Post(const std::string &path, const Headers &headers,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Post(const std::string &path, const Params ¶ms);
- Result Post(const std::string &path, const Headers &headers,
- const Params ¶ms);
- Result Post(const std::string &path, const MultipartFormDataItems &items);
- Result Post(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items);
- Result Post(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items, const std::string &boundary);
- Result Post(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items,
- const MultipartFormDataProviderItems &provider_items);
-
- Result Put(const std::string &path);
- Result Put(const std::string &path, const char *body, size_t content_length,
- const std::string &content_type);
- Result Put(const std::string &path, const Headers &headers, const char *body,
- size_t content_length, const std::string &content_type);
- Result Put(const std::string &path, const std::string &body,
- const std::string &content_type);
- Result Put(const std::string &path, const Headers &headers,
- const std::string &body, const std::string &content_type);
- Result Put(const std::string &path, size_t content_length,
- ContentProvider content_provider, const std::string &content_type);
- Result Put(const std::string &path,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Put(const std::string &path, const Headers &headers,
- size_t content_length, ContentProvider content_provider,
- const std::string &content_type);
- Result Put(const std::string &path, const Headers &headers,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Put(const std::string &path, const Params ¶ms);
- Result Put(const std::string &path, const Headers &headers,
- const Params ¶ms);
- Result Put(const std::string &path, const MultipartFormDataItems &items);
- Result Put(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items);
- Result Put(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items, const std::string &boundary);
- Result Put(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items,
- const MultipartFormDataProviderItems &provider_items);
-
- Result Patch(const std::string &path);
- Result Patch(const std::string &path, const char *body, size_t content_length,
- const std::string &content_type);
- Result Patch(const std::string &path, const Headers &headers,
- const char *body, size_t content_length,
- const std::string &content_type);
- Result Patch(const std::string &path, const std::string &body,
- const std::string &content_type);
- Result Patch(const std::string &path, const Headers &headers,
- const std::string &body, const std::string &content_type);
- Result Patch(const std::string &path, size_t content_length,
- ContentProvider content_provider,
- const std::string &content_type);
- Result Patch(const std::string &path,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Patch(const std::string &path, const Headers &headers,
- size_t content_length, ContentProvider content_provider,
- const std::string &content_type);
- Result Patch(const std::string &path, const Headers &headers,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
-
- Result Delete(const std::string &path);
- Result Delete(const std::string &path, const Headers &headers);
- Result Delete(const std::string &path, const char *body,
- size_t content_length, const std::string &content_type);
- Result Delete(const std::string &path, const Headers &headers,
- const char *body, size_t content_length,
+ Result Post(const std::string &path);
+ Result Post(const std::string &path, const Headers &headers);
+ Result Post(const std::string &path, const char *body, size_t content_length, const std::string &content_type);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
const std::string &content_type);
- Result Delete(const std::string &path, const std::string &body,
+ Result Post(const std::string &path, const std::string &body, const std::string &content_type);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ const std::string &body,
const std::string &content_type);
- Result Delete(const std::string &path, const Headers &headers,
- const std::string &body, const std::string &content_type);
+ Result Post(const std::string &path,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Post(const std::string &path,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
+ Result Post(const std::string &path, const Params ¶ms);
+ Result Post(const std::string &path, const Headers &headers, const Params ¶ms);
+ Result Post(const std::string &path, const MultipartFormDataItems &items);
+ Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ const MultipartFormDataItems &items,
+ const std::string &boundary);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ const MultipartFormDataItems &items,
+ const MultipartFormDataProviderItems &provider_items);
- Result Options(const std::string &path);
- Result Options(const std::string &path, const Headers &headers);
+ Result Put(const std::string &path);
+ Result Put(const std::string &path, const char *body, size_t content_length, const std::string &content_type);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
+ const std::string &content_type);
+ Result Put(const std::string &path, const std::string &body, const std::string &content_type);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ const std::string &body,
+ const std::string &content_type);
+ Result Put(const std::string &path,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Put(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
+ Result Put(const std::string &path, const Params ¶ms);
+ Result Put(const std::string &path, const Headers &headers, const Params ¶ms);
+ Result Put(const std::string &path, const MultipartFormDataItems &items);
+ Result Put(const std::string &path, const Headers &headers, const MultipartFormDataItems &items);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ const MultipartFormDataItems &items,
+ const std::string &boundary);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ const MultipartFormDataItems &items,
+ const MultipartFormDataProviderItems &provider_items);
- bool send(Request &req, Response &res, Error &error);
- Result send(const Request &req);
+ Result Patch(const std::string &path);
+ Result Patch(const std::string &path, const char *body, size_t content_length, const std::string &content_type);
+ Result Patch(const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
+ const std::string &content_type);
+ Result Patch(const std::string &path, const std::string &body, const std::string &content_type);
+ Result Patch(const std::string &path,
+ const Headers &headers,
+ const std::string &body,
+ const std::string &content_type);
+ Result Patch(const std::string &path,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Patch(const std::string &path,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
+ Result Patch(const std::string &path,
+ const Headers &headers,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Patch(const std::string &path,
+ const Headers &headers,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
- void stop();
+ Result Delete(const std::string &path);
+ Result Delete(const std::string &path, const Headers &headers);
+ Result Delete(const std::string &path, const char *body, size_t content_length, const std::string &content_type);
+ Result Delete(const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
+ const std::string &content_type);
+ Result Delete(const std::string &path, const std::string &body, const std::string &content_type);
+ Result Delete(const std::string &path,
+ const Headers &headers,
+ const std::string &body,
+ const std::string &content_type);
- std::string host() const;
- int port() const;
+ Result Options(const std::string &path);
+ Result Options(const std::string &path, const Headers &headers);
- size_t is_socket_open() const;
- socket_t socket() const;
+ bool send(Request &req, Response &res, Error &error);
+ Result send(const Request &req);
- void set_hostname_addr_map(std::map addr_map);
+ void stop();
- void set_default_headers(Headers headers);
+ std::string host() const;
+ int port() const;
- void set_address_family(int family);
- void set_tcp_nodelay(bool on);
- void set_socket_options(SocketOptions socket_options);
+ size_t is_socket_open() const;
+ socket_t socket() const;
- void set_connection_timeout(time_t sec, time_t usec = 0);
- template
- void
- set_connection_timeout(const std::chrono::duration &duration);
+ void set_hostname_addr_map(std::map addr_map);
- void set_read_timeout(time_t sec, time_t usec = 0);
- template
- void set_read_timeout(const std::chrono::duration &duration);
+ void set_default_headers(Headers headers);
- void set_write_timeout(time_t sec, time_t usec = 0);
- template
- void set_write_timeout(const std::chrono::duration &duration);
+ void set_address_family(int family);
+ void set_tcp_nodelay(bool on);
+ void set_socket_options(SocketOptions socket_options);
- void set_basic_auth(const std::string &username, const std::string &password);
- void set_bearer_token_auth(const std::string &token);
+ void set_connection_timeout(time_t sec, time_t usec = 0);
+ template void set_connection_timeout(const std::chrono::duration &duration);
+
+ void set_read_timeout(time_t sec, time_t usec = 0);
+ template void set_read_timeout(const std::chrono::duration &duration);
+
+ void set_write_timeout(time_t sec, time_t usec = 0);
+ template void set_write_timeout(const std::chrono::duration &duration);
+
+ void set_basic_auth(const std::string &username, const std::string &password);
+ void set_bearer_token_auth(const std::string &token);
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- void set_digest_auth(const std::string &username,
- const std::string &password);
+ void set_digest_auth(const std::string &username, const std::string &password);
#endif
- void set_keep_alive(bool on);
- void set_follow_location(bool on);
+ void set_keep_alive(bool on);
+ void set_follow_location(bool on);
- void set_url_encode(bool on);
+ void set_url_encode(bool on);
- void set_compress(bool on);
+ void set_compress(bool on);
- void set_decompress(bool on);
+ void set_decompress(bool on);
- void set_interface(const std::string &intf);
+ void set_interface(const std::string &intf);
- void set_proxy(const std::string &host, int port);
- void set_proxy_basic_auth(const std::string &username,
- const std::string &password);
- void set_proxy_bearer_token_auth(const std::string &token);
+ void set_proxy(const std::string &host, int port);
+ void set_proxy_basic_auth(const std::string &username, const std::string &password);
+ void set_proxy_bearer_token_auth(const std::string &token);
+ void set_post_connect_callback(detail::POSTSOCKETCONNECTCB cb);
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- void set_proxy_digest_auth(const std::string &username,
- const std::string &password);
+ void set_proxy_digest_auth(const std::string &username, const std::string &password);
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- void set_ca_cert_path(const std::string &ca_cert_file_path,
- const std::string &ca_cert_dir_path = std::string());
- void set_ca_cert_store(X509_STORE *ca_cert_store);
- X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size);
+ void set_ca_cert_path(const std::string &ca_cert_file_path, const std::string &ca_cert_dir_path = std::string());
+ void set_ca_cert_store(X509_STORE *ca_cert_store);
+ X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size);
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- void enable_server_certificate_verification(bool enabled);
+ void enable_server_certificate_verification(bool enabled);
#endif
- void set_logger(Logger logger);
+ void set_logger(Logger logger);
protected:
- struct Socket {
- socket_t sock = INVALID_SOCKET;
+ struct Socket {
+ socket_t sock = INVALID_SOCKET;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- SSL *ssl = nullptr;
+ SSL *ssl = nullptr;
#endif
- bool is_open() const { return sock != INVALID_SOCKET; }
- };
+ bool is_open() const {
+ return sock != INVALID_SOCKET;
+ }
+ };
- virtual bool create_and_connect_socket(Socket &socket, Error &error);
+ virtual bool create_and_connect_socket(Socket &socket, Error &error);
- // All of:
- // shutdown_ssl
- // shutdown_socket
- // close_socket
- // should ONLY be called when socket_mutex_ is locked.
- // Also, shutdown_ssl and close_socket should also NOT be called concurrently
- // with a DIFFERENT thread sending requests using that socket.
- virtual void shutdown_ssl(Socket &socket, bool shutdown_gracefully);
- void shutdown_socket(Socket &socket);
- void close_socket(Socket &socket);
+ // All of:
+ // shutdown_ssl
+ // shutdown_socket
+ // close_socket
+ // should ONLY be called when socket_mutex_ is locked.
+ // Also, shutdown_ssl and close_socket should also NOT be called concurrently
+ // with a DIFFERENT thread sending requests using that socket.
+ virtual void shutdown_ssl(Socket &socket, bool shutdown_gracefully);
+ void shutdown_socket(Socket &socket);
+ void close_socket(Socket &socket);
- bool process_request(Stream &strm, Request &req, Response &res,
- bool close_connection, Error &error);
+ bool process_request(Stream &strm, Request &req, Response &res, bool close_connection, Error &error);
- bool write_content_with_provider(Stream &strm, const Request &req,
- Error &error);
+ bool write_content_with_provider(Stream &strm, const Request &req, Error &error);
- void copy_settings(const ClientImpl &rhs);
+ void copy_settings(const ClientImpl &rhs);
- // Socket endpoint information
- const std::string host_;
- const int port_;
- const std::string host_and_port_;
+ // Socket endpoint information
+ const std::string host_;
+ const int port_;
+ const std::string host_and_port_;
- // Current open socket
- Socket socket_;
- mutable std::mutex socket_mutex_;
- std::recursive_mutex request_mutex_;
+ // Current open socket
+ Socket socket_;
+ mutable std::mutex socket_mutex_;
+ std::recursive_mutex request_mutex_;
- // These are all protected under socket_mutex
- size_t socket_requests_in_flight_ = 0;
- std::thread::id socket_requests_are_from_thread_ = std::thread::id();
- bool socket_should_be_closed_when_request_is_done_ = false;
+ // These are all protected under socket_mutex
+ size_t socket_requests_in_flight_ = 0;
+ std::thread::id socket_requests_are_from_thread_ = std::thread::id();
+ bool socket_should_be_closed_when_request_is_done_ = false;
- // Hostname-IP map
- std::map addr_map_;
+ // Hostname-IP map
+ std::map addr_map_;
- // Default headers
- Headers default_headers_;
+ // Default headers
+ Headers default_headers_;
- // Settings
- std::string client_cert_path_;
- std::string client_key_path_;
+ // Settings
+ std::string client_cert_path_;
+ std::string client_key_path_;
- time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND;
- time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
- time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
- time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
- time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
- time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
+ time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND;
+ time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
+ time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
+ time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
+ time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
+ time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
- std::string basic_auth_username_;
- std::string basic_auth_password_;
- std::string bearer_token_auth_token_;
+ std::string basic_auth_username_;
+ std::string basic_auth_password_;
+ std::string bearer_token_auth_token_;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- std::string digest_auth_username_;
- std::string digest_auth_password_;
+ std::string digest_auth_username_;
+ std::string digest_auth_password_;
#endif
- bool keep_alive_ = false;
- bool follow_location_ = false;
+ bool keep_alive_ = false;
+ bool follow_location_ = false;
- bool url_encode_ = true;
+ bool url_encode_ = true;
- int address_family_ = AF_UNSPEC;
- bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
- SocketOptions socket_options_ = nullptr;
+ int address_family_ = AF_UNSPEC;
+ bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
+ SocketOptions socket_options_ = nullptr;
- bool compress_ = false;
- bool decompress_ = true;
+ bool compress_ = false;
+ bool decompress_ = true;
- std::string interface_;
+ std::string interface_;
- std::string proxy_host_;
- int proxy_port_ = -1;
+ std::string proxy_host_;
+ int proxy_port_ = -1;
- std::string proxy_basic_auth_username_;
- std::string proxy_basic_auth_password_;
- std::string proxy_bearer_token_auth_token_;
+ std::string proxy_basic_auth_username_;
+ std::string proxy_basic_auth_password_;
+ std::string proxy_bearer_token_auth_token_;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- std::string proxy_digest_auth_username_;
- std::string proxy_digest_auth_password_;
+ std::string proxy_digest_auth_username_;
+ std::string proxy_digest_auth_password_;
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- std::string ca_cert_file_path_;
- std::string ca_cert_dir_path_;
+ std::string ca_cert_file_path_;
+ std::string ca_cert_dir_path_;
- X509_STORE *ca_cert_store_ = nullptr;
+ X509_STORE *ca_cert_store_ = nullptr;
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- bool server_certificate_verification_ = true;
+ bool server_certificate_verification_ = true;
#endif
- Logger logger_;
+ Logger logger_;
+
+ detail::POSTSOCKETCONNECTCB _postConnCb = nullptr;
private:
- bool send_(Request &req, Response &res, Error &error);
- Result send_(Request &&req);
+ bool send_(Request &req, Response &res, Error &error);
+ Result send_(Request &&req);
- socket_t create_client_socket(Error &error) const;
- bool read_response_line(Stream &strm, const Request &req, Response &res);
- bool write_request(Stream &strm, Request &req, bool close_connection,
- Error &error);
- bool redirect(Request &req, Response &res, Error &error);
- bool handle_request(Stream &strm, Request &req, Response &res,
- bool close_connection, Error &error);
- std::unique_ptr send_with_content_provider(
- Request &req, const char *body, size_t content_length,
- ContentProvider content_provider,
- ContentProviderWithoutLength content_provider_without_length,
- const std::string &content_type, Error &error);
- Result send_with_content_provider(
- const std::string &method, const std::string &path,
- const Headers &headers, const char *body, size_t content_length,
- ContentProvider content_provider,
- ContentProviderWithoutLength content_provider_without_length,
- const std::string &content_type);
- ContentProviderWithoutLength get_multipart_content_provider(
- const std::string &boundary, const MultipartFormDataItems &items,
- const MultipartFormDataProviderItems &provider_items);
+ socket_t create_client_socket(Error &error) const;
+ bool read_response_line(Stream &strm, const Request &req, Response &res);
+ bool write_request(Stream &strm, Request &req, bool close_connection, Error &error);
+ bool redirect(Request &req, Response &res, Error &error);
+ bool handle_request(Stream &strm, Request &req, Response &res, bool close_connection, Error &error);
+ std::unique_ptr send_with_content_provider(Request &req,
+ const char *body,
+ size_t content_length,
+ ContentProvider content_provider,
+ ContentProviderWithoutLength content_provider_without_length,
+ const std::string &content_type,
+ Error &error);
+ Result send_with_content_provider(const std::string &method,
+ const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
+ ContentProvider content_provider,
+ ContentProviderWithoutLength content_provider_without_length,
+ const std::string &content_type);
+ ContentProviderWithoutLength get_multipart_content_provider(const std::string &boundary,
+ const MultipartFormDataItems &items,
+ const MultipartFormDataProviderItems &provider_items);
- std::string adjust_host_string(const std::string &host) const;
+ std::string adjust_host_string(const std::string &host) const;
- virtual bool process_socket(const Socket &socket,
- std::function callback);
- virtual bool is_ssl() const;
+ virtual bool process_socket(const Socket &socket, std::function callback);
+ virtual bool is_ssl() const;
};
class Client {
public:
- // Universal interface
- explicit Client(const std::string &scheme_host_port);
+ // Universal interface
+ explicit Client(const std::string &scheme_host_port);
- explicit Client(const std::string &scheme_host_port,
- const std::string &client_cert_path,
- const std::string &client_key_path);
+ explicit Client(const std::string &scheme_host_port,
+ const std::string &client_cert_path,
+ const std::string &client_key_path);
- // HTTP only interface
- explicit Client(const std::string &host, int port);
+ // HTTP only interface
+ explicit Client(const std::string &host, int port);
- explicit Client(const std::string &host, int port,
- const std::string &client_cert_path,
- const std::string &client_key_path);
+ explicit Client(const std::string &host,
+ int port,
+ const std::string &client_cert_path,
+ const std::string &client_key_path);
- Client(Client &&) = default;
+ Client(Client &&) = default;
- ~Client();
+ ~Client();
- bool is_valid() const;
+ bool is_valid() const;
- Result Get(const std::string &path);
- Result Get(const std::string &path, const Headers &headers);
- Result Get(const std::string &path, Progress progress);
- Result Get(const std::string &path, const Headers &headers,
- Progress progress);
- Result Get(const std::string &path, ContentReceiver content_receiver);
- Result Get(const std::string &path, const Headers &headers,
- ContentReceiver content_receiver);
- Result Get(const std::string &path, ContentReceiver content_receiver,
- Progress progress);
- Result Get(const std::string &path, const Headers &headers,
- ContentReceiver content_receiver, Progress progress);
- Result Get(const std::string &path, ResponseHandler response_handler,
- ContentReceiver content_receiver);
- Result Get(const std::string &path, const Headers &headers,
- ResponseHandler response_handler,
- ContentReceiver content_receiver);
- Result Get(const std::string &path, const Headers &headers,
- ResponseHandler response_handler, ContentReceiver content_receiver,
- Progress progress);
- Result Get(const std::string &path, ResponseHandler response_handler,
- ContentReceiver content_receiver, Progress progress);
+ Result Get(const std::string &path);
+ Result Get(const std::string &path, const Headers &headers);
+ Result Get(const std::string &path, Progress progress);
+ Result Get(const std::string &path, const Headers &headers, Progress progress);
+ Result Get(const std::string &path, ContentReceiver content_receiver);
+ Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver);
+ Result Get(const std::string &path, ContentReceiver content_receiver, Progress progress);
+ Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, Progress progress);
+ Result Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver);
+ Result Get(const std::string &path,
+ const Headers &headers,
+ ResponseHandler response_handler,
+ ContentReceiver content_receiver);
+ Result Get(const std::string &path,
+ const Headers &headers,
+ ResponseHandler response_handler,
+ ContentReceiver content_receiver,
+ Progress progress);
+ Result Get(const std::string &path,
+ ResponseHandler response_handler,
+ ContentReceiver content_receiver,
+ Progress progress);
- Result Get(const std::string &path, const Params ¶ms,
- const Headers &headers, Progress progress = nullptr);
- Result Get(const std::string &path, const Params ¶ms,
- const Headers &headers, ContentReceiver content_receiver,
- Progress progress = nullptr);
- Result Get(const std::string &path, const Params ¶ms,
- const Headers &headers, ResponseHandler response_handler,
- ContentReceiver content_receiver, Progress progress = nullptr);
+ Result Get(const std::string &path, const Params ¶ms, const Headers &headers, Progress progress = nullptr);
+ Result Get(const std::string &path,
+ const Params ¶ms,
+ const Headers &headers,
+ ContentReceiver content_receiver,
+ Progress progress = nullptr);
+ Result Get(const std::string &path,
+ const Params ¶ms,
+ const Headers &headers,
+ ResponseHandler response_handler,
+ ContentReceiver content_receiver,
+ Progress progress = nullptr);
- Result Head(const std::string &path);
- Result Head(const std::string &path, const Headers &headers);
+ Result Head(const std::string &path);
+ Result Head(const std::string &path, const Headers &headers);
- Result Post(const std::string &path);
- Result Post(const std::string &path, const Headers &headers);
- Result Post(const std::string &path, const char *body, size_t content_length,
- const std::string &content_type);
- Result Post(const std::string &path, const Headers &headers, const char *body,
- size_t content_length, const std::string &content_type);
- Result Post(const std::string &path, const std::string &body,
- const std::string &content_type);
- Result Post(const std::string &path, const Headers &headers,
- const std::string &body, const std::string &content_type);
- Result Post(const std::string &path, size_t content_length,
- ContentProvider content_provider,
- const std::string &content_type);
- Result Post(const std::string &path,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Post(const std::string &path, const Headers &headers,
- size_t content_length, ContentProvider content_provider,
- const std::string &content_type);
- Result Post(const std::string &path, const Headers &headers,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Post(const std::string &path, const Params ¶ms);
- Result Post(const std::string &path, const Headers &headers,
- const Params ¶ms);
- Result Post(const std::string &path, const MultipartFormDataItems &items);
- Result Post(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items);
- Result Post(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items, const std::string &boundary);
- Result Post(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items,
- const MultipartFormDataProviderItems &provider_items);
-
- Result Put(const std::string &path);
- Result Put(const std::string &path, const char *body, size_t content_length,
- const std::string &content_type);
- Result Put(const std::string &path, const Headers &headers, const char *body,
- size_t content_length, const std::string &content_type);
- Result Put(const std::string &path, const std::string &body,
- const std::string &content_type);
- Result Put(const std::string &path, const Headers &headers,
- const std::string &body, const std::string &content_type);
- Result Put(const std::string &path, size_t content_length,
- ContentProvider content_provider, const std::string &content_type);
- Result Put(const std::string &path,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Put(const std::string &path, const Headers &headers,
- size_t content_length, ContentProvider content_provider,
- const std::string &content_type);
- Result Put(const std::string &path, const Headers &headers,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Put(const std::string &path, const Params ¶ms);
- Result Put(const std::string &path, const Headers &headers,
- const Params ¶ms);
- Result Put(const std::string &path, const MultipartFormDataItems &items);
- Result Put(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items);
- Result Put(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items, const std::string &boundary);
- Result Put(const std::string &path, const Headers &headers,
- const MultipartFormDataItems &items,
- const MultipartFormDataProviderItems &provider_items);
-
- Result Patch(const std::string &path);
- Result Patch(const std::string &path, const char *body, size_t content_length,
- const std::string &content_type);
- Result Patch(const std::string &path, const Headers &headers,
- const char *body, size_t content_length,
- const std::string &content_type);
- Result Patch(const std::string &path, const std::string &body,
- const std::string &content_type);
- Result Patch(const std::string &path, const Headers &headers,
- const std::string &body, const std::string &content_type);
- Result Patch(const std::string &path, size_t content_length,
- ContentProvider content_provider,
- const std::string &content_type);
- Result Patch(const std::string &path,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
- Result Patch(const std::string &path, const Headers &headers,
- size_t content_length, ContentProvider content_provider,
- const std::string &content_type);
- Result Patch(const std::string &path, const Headers &headers,
- ContentProviderWithoutLength content_provider,
- const std::string &content_type);
-
- Result Delete(const std::string &path);
- Result Delete(const std::string &path, const Headers &headers);
- Result Delete(const std::string &path, const char *body,
- size_t content_length, const std::string &content_type);
- Result Delete(const std::string &path, const Headers &headers,
- const char *body, size_t content_length,
+ Result Post(const std::string &path);
+ Result Post(const std::string &path, const Headers &headers);
+ Result Post(const std::string &path, const char *body, size_t content_length, const std::string &content_type);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
const std::string &content_type);
- Result Delete(const std::string &path, const std::string &body,
+ Result Post(const std::string &path, const std::string &body, const std::string &content_type);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ const std::string &body,
const std::string &content_type);
- Result Delete(const std::string &path, const Headers &headers,
- const std::string &body, const std::string &content_type);
+ Result Post(const std::string &path,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Post(const std::string &path,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
+ Result Post(const std::string &path, const Params ¶ms);
+ Result Post(const std::string &path, const Headers &headers, const Params ¶ms);
+ Result Post(const std::string &path, const MultipartFormDataItems &items);
+ Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ const MultipartFormDataItems &items,
+ const std::string &boundary);
+ Result Post(const std::string &path,
+ const Headers &headers,
+ const MultipartFormDataItems &items,
+ const MultipartFormDataProviderItems &provider_items);
- Result Options(const std::string &path);
- Result Options(const std::string &path, const Headers &headers);
+ Result Put(const std::string &path);
+ Result Put(const std::string &path, const char *body, size_t content_length, const std::string &content_type);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
+ const std::string &content_type);
+ Result Put(const std::string &path, const std::string &body, const std::string &content_type);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ const std::string &body,
+ const std::string &content_type);
+ Result Put(const std::string &path,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Put(const std::string &path, ContentProviderWithoutLength content_provider, const std::string &content_type);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
+ Result Put(const std::string &path, const Params ¶ms);
+ Result Put(const std::string &path, const Headers &headers, const Params ¶ms);
+ Result Put(const std::string &path, const MultipartFormDataItems &items);
+ Result Put(const std::string &path, const Headers &headers, const MultipartFormDataItems &items);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ const MultipartFormDataItems &items,
+ const std::string &boundary);
+ Result Put(const std::string &path,
+ const Headers &headers,
+ const MultipartFormDataItems &items,
+ const MultipartFormDataProviderItems &provider_items);
- bool send(Request &req, Response &res, Error &error);
- Result send(const Request &req);
+ Result Patch(const std::string &path);
+ Result Patch(const std::string &path, const char *body, size_t content_length, const std::string &content_type);
+ Result Patch(const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
+ const std::string &content_type);
+ Result Patch(const std::string &path, const std::string &body, const std::string &content_type);
+ Result Patch(const std::string &path,
+ const Headers &headers,
+ const std::string &body,
+ const std::string &content_type);
+ Result Patch(const std::string &path,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Patch(const std::string &path,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
+ Result Patch(const std::string &path,
+ const Headers &headers,
+ size_t content_length,
+ ContentProvider content_provider,
+ const std::string &content_type);
+ Result Patch(const std::string &path,
+ const Headers &headers,
+ ContentProviderWithoutLength content_provider,
+ const std::string &content_type);
- void stop();
+ Result Delete(const std::string &path);
+ Result Delete(const std::string &path, const Headers &headers);
+ Result Delete(const std::string &path, const char *body, size_t content_length, const std::string &content_type);
+ Result Delete(const std::string &path,
+ const Headers &headers,
+ const char *body,
+ size_t content_length,
+ const std::string &content_type);
+ Result Delete(const std::string &path, const std::string &body, const std::string &content_type);
+ Result Delete(const std::string &path,
+ const Headers &headers,
+ const std::string &body,
+ const std::string &content_type);
- std::string host() const;
- int port() const;
+ Result Options(const std::string &path);
+ Result Options(const std::string &path, const Headers &headers);
- size_t is_socket_open() const;
- socket_t socket() const;
+ bool send(Request &req, Response &res, Error &error);
+ Result send(const Request &req);
- void set_hostname_addr_map(std::map addr_map);
+ void stop();
- void set_default_headers(Headers headers);
+ std::string host() const;
+ int port() const;
- void set_address_family(int family);
- void set_tcp_nodelay(bool on);
- void set_socket_options(SocketOptions socket_options);
+ size_t is_socket_open() const;
+ socket_t socket() const;
- void set_connection_timeout(time_t sec, time_t usec = 0);
- template
- void
- set_connection_timeout(const std::chrono::duration &duration);
+ void set_hostname_addr_map(std::map addr_map);
- void set_read_timeout(time_t sec, time_t usec = 0);
- template
- void set_read_timeout(const std::chrono::duration &duration);
+ void set_default_headers(Headers headers);
- void set_write_timeout(time_t sec, time_t usec = 0);
- template
- void set_write_timeout(const std::chrono::duration &duration);
+ void set_address_family(int family);
+ void set_tcp_nodelay(bool on);
+ void set_socket_options(SocketOptions socket_options);
- void set_basic_auth(const std::string &username, const std::string &password);
- void set_bearer_token_auth(const std::string &token);
+ void set_connection_timeout(time_t sec, time_t usec = 0);
+ template void set_connection_timeout(const std::chrono::duration &duration);
+
+ void set_read_timeout(time_t sec, time_t usec = 0);
+ template void set_read_timeout(const std::chrono::duration &duration);
+
+ void set_write_timeout(time_t sec, time_t usec = 0);
+ template void set_write_timeout(const std::chrono::duration &duration);
+
+ void set_basic_auth(const std::string &username, const std::string &password);
+ void set_bearer_token_auth(const std::string &token);
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- void set_digest_auth(const std::string &username,
- const std::string &password);
+ void set_digest_auth(const std::string &username, const std::string &password);
#endif
- void set_keep_alive(bool on);
- void set_follow_location(bool on);
+ void set_keep_alive(bool on);
+ void set_follow_location(bool on);
- void set_url_encode(bool on);
+ void set_url_encode(bool on);
- void set_compress(bool on);
+ void set_compress(bool on);
- void set_decompress(bool on);
+ void set_decompress(bool on);
- void set_interface(const std::string &intf);
+ void set_interface(const std::string &intf);
- void set_proxy(const std::string &host, int port);
- void set_proxy_basic_auth(const std::string &username,
- const std::string &password);
- void set_proxy_bearer_token_auth(const std::string &token);
+ void set_proxy(const std::string &host, int port);
+ void set_proxy_basic_auth(const std::string &username, const std::string &password);
+ void set_proxy_bearer_token_auth(const std::string &token);
+ void set_post_connect_cb(detail::POSTSOCKETCONNECTCB cb);
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- void set_proxy_digest_auth(const std::string &username,
- const std::string &password);
+ void set_proxy_digest_auth(const std::string &username, const std::string &password);
#endif
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- void enable_server_certificate_verification(bool enabled);
+ void enable_server_certificate_verification(bool enabled);
#endif
- void set_logger(Logger logger);
+ void set_logger(Logger logger);
- // SSL
+ // SSL
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- void set_ca_cert_path(const std::string &ca_cert_file_path,
- const std::string &ca_cert_dir_path = std::string());
+ void set_ca_cert_path(const std::string &ca_cert_file_path, const std::string &ca_cert_dir_path = std::string());
- void set_ca_cert_store(X509_STORE *ca_cert_store);
- void load_ca_cert_store(const char *ca_cert, std::size_t size);
+ void set_ca_cert_store(X509_STORE *ca_cert_store);
+ void load_ca_cert_store(const char *ca_cert, std::size_t size);
- long get_openssl_verify_result() const;
+ long get_openssl_verify_result() const;
- SSL_CTX *ssl_context() const;
+ SSL_CTX *ssl_context() const;
#endif
private:
- std::unique_ptr cli_;
+ std::unique_ptr cli_;
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
- bool is_ssl_ = false;
+ bool is_ssl_ = false;
#endif
};
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
class SSLServer : public Server {
public:
- SSLServer(const char *cert_path, const char *private_key_path,
- const char *client_ca_cert_file_path = nullptr,
- const char *client_ca_cert_dir_path = nullptr,
- const char *private_key_password = nullptr);
+ SSLServer(const char *cert_path,
+ const char *private_key_path,
+ const char *client_ca_cert_file_path = nullptr,
+ const char *client_ca_cert_dir_path = nullptr,
+ const char *private_key_password = nullptr);
- SSLServer(X509 *cert, EVP_PKEY *private_key,
- X509_STORE *client_ca_cert_store = nullptr);
+ SSLServer(X509 *cert, EVP_PKEY *private_key, X509_STORE *client_ca_cert_store = nullptr);
- SSLServer(
- const std::function &setup_ssl_ctx_callback);
+ SSLServer(const std::function &setup_ssl_ctx_callback);
- ~SSLServer() override;
+ ~SSLServer() override;
- bool is_valid() const override;
+ bool is_valid() const override;
- SSL_CTX *ssl_context() const;
+ SSL_CTX *ssl_context() const;
private:
- bool process_and_close_socket(socket_t sock) override;
+ bool process_and_close_socket(socket_t sock) override;
- SSL_CTX *ctx_;
- std::mutex ctx_mutex_;
+ SSL_CTX *ctx_;
+ std::mutex ctx_mutex_;
};
class SSLClient : public ClientImpl {
public:
- explicit SSLClient(const std::string &host);
+ explicit SSLClient(const std::string &host);
- explicit SSLClient(const std::string &host, int port);
+ explicit SSLClient(const std::string &host, int port);
- explicit SSLClient(const std::string &host, int port,
- const std::string &client_cert_path,
- const std::string &client_key_path);
+ explicit SSLClient(const std::string &host,
+ int port,
+ const std::string &client_cert_path,
+ const std::string &client_key_path);
- explicit SSLClient(const std::string &host, int port, X509 *client_cert,
- EVP_PKEY *client_key);
+ explicit SSLClient(const std::string &host, int port, X509 *client_cert, EVP_PKEY *client_key);
- ~SSLClient() override;
+ ~SSLClient() override;
- bool is_valid() const override;
+ bool is_valid() const override;
- void set_ca_cert_store(X509_STORE *ca_cert_store);
- void load_ca_cert_store(const char *ca_cert, std::size_t size);
+ void set_ca_cert_store(X509_STORE *ca_cert_store);
+ void load_ca_cert_store(const char *ca_cert, std::size_t size);
- long get_openssl_verify_result() const;
+ long get_openssl_verify_result() const;
- SSL_CTX *ssl_context() const;
+ SSL_CTX *ssl_context() const;
private:
- bool create_and_connect_socket(Socket &socket, Error &error) override;
- void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override;
- void shutdown_ssl_impl(Socket &socket, bool shutdown_socket);
+ bool create_and_connect_socket(Socket &socket, Error &error) override;
+ void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override;
+ void shutdown_ssl_impl(Socket &socket, bool shutdown_socket);
- bool process_socket(const Socket &socket,
- std::function callback) override;
- bool is_ssl() const override;
+ bool process_socket(const Socket &socket, std::function callback) override;
+ bool is_ssl() const override;
- bool connect_with_proxy(Socket &sock, Response &res, bool &success,
- Error &error);
- bool initialize_ssl(Socket &socket, Error &error);
+ bool connect_with_proxy(Socket &sock, Response &res, bool &success, Error &error);
+ bool initialize_ssl(Socket &socket, Error &error);
- bool load_certs();
+ bool load_certs();
- bool verify_host(X509 *server_cert) const;
- bool verify_host_with_subject_alt_name(X509 *server_cert) const;
- bool verify_host_with_common_name(X509 *server_cert) const;
- bool check_host_name(const char *pattern, size_t pattern_len) const;
+ bool verify_host(X509 *server_cert) const;
+ bool verify_host_with_subject_alt_name(X509 *server_cert) const;
+ bool verify_host_with_common_name(X509 *server_cert) const;
+ bool check_host_name(const char *pattern, size_t pattern_len) const;
- SSL_CTX *ctx_;
- std::mutex ctx_mutex_;
- std::once_flag initialize_cert_;
+ SSL_CTX *ctx_;
+ std::mutex ctx_mutex_;
+ std::once_flag initialize_cert_;
- std::vector host_components_;
+ std::vector host_components_;
- long verify_result_ = 0;
+ long verify_result_ = 0;
- friend class ClientImpl;
+ friend class ClientImpl;
};
#endif
@@ -1695,184 +1764,171 @@ private:
namespace detail {
-template
-inline void duration_to_sec_and_usec(const T &duration, U callback) {
- auto sec = std::chrono::duration_cast(duration).count();
- auto usec = std::chrono::duration_cast(
- duration - std::chrono::seconds(sec))
- .count();
- callback(static_cast(sec), static_cast(usec));
+template inline void duration_to_sec_and_usec(const T &duration, U callback) {
+ auto sec = std::chrono::duration_cast(duration).count();
+ auto usec = std::chrono::duration_cast(duration - std::chrono::seconds(sec)).count();
+ callback(static_cast(sec), static_cast(usec));
}
-template
+template
inline T get_header_value(const Headers & /*headers*/,
- const std::string & /*key*/, size_t /*id*/ = 0,
- uint64_t /*def*/ = 0) {}
-
-template <>
-inline uint64_t get_header_value(const Headers &headers,
- const std::string &key, size_t id,
- uint64_t def) {
- auto rng = headers.equal_range(key);
- auto it = rng.first;
- std::advance(it, static_cast(id));
- if (it != rng.second) {
- return std::strtoull(it->second.data(), nullptr, 10);
- }
- return def;
+ const std::string & /*key*/,
+ size_t /*id*/ = 0,
+ uint64_t /*def*/ = 0) {
}
-} // namespace detail
-
-template
-inline T Request::get_header_value(const std::string &key, size_t id) const {
- return detail::get_header_value(headers, key, id, 0);
-}
-
-template
-inline T Response::get_header_value(const std::string &key, size_t id) const {
- return detail::get_header_value(headers, key, id, 0);
-}
-
-template
-inline ssize_t Stream::write_format(const char *fmt, const Args &...args) {
- const auto bufsiz = 2048;
- std::array buf{};
-
- auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...);
- if (sn <= 0) { return sn; }
-
- auto n = static_cast(sn);
-
- if (n >= buf.size() - 1) {
- std::vector glowable_buf(buf.size());
-
- while (n >= glowable_buf.size() - 1) {
- glowable_buf.resize(glowable_buf.size() * 2);
- n = static_cast(
- snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...));
+template<>
+inline uint64_t get_header_value(const Headers &headers, const std::string &key, size_t id, uint64_t def) {
+ auto rng = headers.equal_range(key);
+ auto it = rng.first;
+ std::advance(it, static_cast(id));
+ if (it != rng.second) {
+ return std::strtoull(it->second.data(), nullptr, 10);
+ }
+ return def;
+}
+
+} // namespace detail
+
+template inline T Request::get_header_value(const std::string &key, size_t id) const {
+ return detail::get_header_value(headers, key, id, 0);
+}
+
+template inline T Response::get_header_value(const std::string &key, size_t id) const {
+ return detail::get_header_value(headers, key, id, 0);
+}
+
+template inline ssize_t Stream::write_format(const char *fmt, const Args &...args) {
+ const auto bufsiz = 2048;
+ std::array buf {};
+
+ auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...);
+ if (sn <= 0) {
+ return sn;
+ }
+
+ auto n = static_cast(sn);
+
+ if (n >= buf.size() - 1) {
+ std::vector glowable_buf(buf.size());
+
+ while (n >= glowable_buf.size() - 1) {
+ glowable_buf.resize(glowable_buf.size() * 2);
+ n = static_cast(snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...));
+ }
+ return write(&glowable_buf[0], n);
+ } else {
+ return write(buf.data(), n);
}
- return write(&glowable_buf[0], n);
- } else {
- return write(buf.data(), n);
- }
}
inline void default_socket_options(socket_t sock) {
- int yes = 1;
+ int yes = 1;
#ifdef _WIN32
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- reinterpret_cast(&yes), sizeof(yes));
- setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
- reinterpret_cast(&yes), sizeof(yes));
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), sizeof(yes));
+ setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, reinterpret_cast(&yes), sizeof(yes));
#else
#ifdef SO_REUSEPORT
- setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
- reinterpret_cast(&yes), sizeof(yes));
+ setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast(&yes), sizeof(yes));
#else
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
- reinterpret_cast(&yes), sizeof(yes));
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), sizeof(yes));
#endif
#endif
}
-template
-inline Server &
-Server::set_read_timeout(const std::chrono::duration