Sfoglia il codice sorgente

Windows HTTP client code (untested)

Adam Ierymenko 11 anni fa
parent
commit
7eccc5ebf2

+ 151 - 0
node/HttpClient.cpp

@@ -51,6 +51,13 @@
 #include <sys/wait.h>
 #endif
 
+#ifdef __WINDOWS__
+#include <locale>
+#include <codecvt>
+#include <Windows.h>
+#include <winhttp.h>
+#endif
+
 namespace ZeroTier {
 
 const std::map<std::string,std::string> HttpClient::NO_HEADERS;
@@ -308,4 +315,148 @@ HttpClient::Request HttpClient::_do(
 
 #endif
 
+#ifdef __WINDOWS__
+
+#define WIN_MAX_MESSAGE_LENGTH (1024 * 1024 * 64)
+
+// Internal private thread class that performs request, notifies handler,
+// and then commits suicide by deleting itself.
+class P_Req : NonCopyable
+{
+public:
+	P_Req(const char *method,const std::string &url,const std::map<std::string,std::string> &headers,unsigned int timeout,void (*handler)(void *,int,const std::string &,bool,const std::string &),void *arg) :
+		_url(url),
+		_headers(headers),
+		_timeout(timeout),
+		_handler(handler),
+		_arg(arg)
+	{
+		_myThread = Thread::start(this);
+	}
+
+	void threadMain()
+	{
+		HINTERNET hSession = (HINTERNET)0;
+		HINTERNET hConnect = (HINTERNET)0;
+		HINTERNET hRequest = (HINTERNET)0;
+
+		try {
+			hSession = WinHttpOpen(L"ZeroTier One HttpClient/1.0",WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,WINHTTP_NO_PROXY_NAME,WINHTTP_NO_PROXY_BYPASS,0);
+			if (!hSession) {
+				_handler(_arg,-1,_url,false,"WinHttpOpen() failed");
+				goto closeAndReturnFromHttp;
+			}
+			int timeoutMs = (int)_timeout * 1000;
+			WinHttpSetTimeouts(hSession,timeoutMs,timeoutMs,timeoutMs,timeoutMs);
+
+			std::wstring_convert< std::codecvt_utf8<wchar_t> > wcconv;
+			std::wstring wurl(wcconv.from_bytes(_url));
+
+			URL_COMPONENTS uc;
+			memset(&uc,0,sizeof(uc));
+			uc.dwStructSize = sizeof(uc);
+			uc.dwSchemeLength = -1;
+			uc.dwHostNameLength = -1;
+			uc.dwUrlPathLength = -1;
+			uc.dwExtraInfoLength = -1;
+			if (!WinHttpCrackUrl(wurl.c_str(),wurl.length(),0,&uc)) {
+				_handler(_arg,-1,_url,false,"unable to parse URL: WinHttpCrackUrl() failed");
+				goto closeAndReturnFromHttp;
+			}
+			if ((!uc.lpszHostName)||(!uc.lpszUrlPath)||(!uc.lpszScheme)||(uc.dwHostNameLength <= 0)||(uc.dwUrlPathLength <= 0)||(uc.dwSchemeLength <= 0)) {
+				_handler(_arg,-1,_url,false,"unable to parse URL: missing scheme, host name, or path");
+				goto closeAndReturnFromHttp;
+			}
+			std::wstring urlScheme(uc.lpszScheme,uc.dwSchemeLength);
+			std::wstring urlHostName(uc.lpszHostName,uc.dwHostNameLength);
+			std::wstring urlPath(uc.lpszUrlPath,uc.dwUrlPathLength);
+			if ((uc.lpszExtraInfo)&&(uc.dwExtraInfoLength > 0))
+				urlPath.append(uc.lpszExtraInfo,uc.dwExtraInfoLength);
+
+			if (urlScheme != L"http") {
+				_handler(_arg,-1,_url,false,"only 'http' scheme is supported");
+				goto closeAndReturnFromHttp;
+			}
+
+			hConnect = WinHttpConnect(hSession,urlHostName.c_str(),((uc.nPort > 0) ? uc.nPort : 80),0);
+			if (!hConnect) {
+				_handler(_arg,-1,_url,false,"connection failed");
+				goto closeAndReturnFromHttp;
+			}
+
+			hRequest = WinHttpOpenRequest(hConnect,L"GET",NULL,NULL,WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES,0);
+			if (!hRequest) {
+				_handler(_arg,-1,_url,false,"error sending request");
+				goto closeAndReturnFromHttp;
+			}
+
+			if (WinHttpReceiveResponse(hRequest,NULL)) {
+				DWORD dwStatusCode = 0;
+				DWORD dwTmp = sizeof(dwStatusCode);
+				WinHttpQueryHeaders(hRequest,WINHTTP_QUERY_STATUS_CODE| WINHTTP_QUERY_FLAG_NUMBER,NULL,&dwStatusCode,&dwTmp,NULL);
+
+				DWORD dwSize;
+				do {
+					dwSize = 0;
+					if (!WinHttpQueryDataAvailable(hRequest,&dwSize)) {
+						_handler(_arg,-1,_url,false,"receive error (1)");
+						goto closeAndReturnFromHttp;
+					}
+
+					char *outBuffer = new char[dwSize];
+					DWORD dwRead = 0;
+					if (!WinHttpReadData(hRequest,(LPVOID)outBuffer,dwSize,&dwRead)) {
+						_handler(_arg,-1,_url,false,"receive error (2)");
+						goto closeAndReturnFromHttp;
+					}
+
+					_body.append(outBuffer,dwRead);
+					delete [] outBuffer;
+					if (_body.length() > WIN_MAX_MESSAGE_LENGTH) {
+						_handler(_arg,-1,_url,false,"result too large");
+						goto closeAndReturnFromHttp;
+					}
+				} while (dwSize > 0);
+
+				_handler(_arg,dwStatusCode,_url,false,_body);
+			}
+		} catch (std::bad_alloc &exc) {
+			_handler(_arg,-1,_url,false,"insufficient memory");
+		} catch ( ... ) {
+			_handler(_arg,-1,_url,false,"unexpected exception");
+		}
+
+closeAndReturnFromHttp:
+		if (hRequest)
+			WinHttpCloseHandle(hRequest);
+		if (hConnect)
+			WinHttpCloseHandle(hConnect);
+		if (hSession)
+			WinHttpCloseHandle(hSession);
+		delete this;
+		return;
+	}
+
+	const std::string _url;
+	std::string _body;
+	std::map<std::string,std::string> _headers;
+	unsigned int _timeout;
+	void (*_handler)(void *,int,const std::string &,bool,const std::string &);
+	void *_arg;
+	Thread _myThread;
+};
+
+HttpClient::Request HttpClient::_do(
+	const char *method,
+	const std::string &url,
+	const std::map<std::string,std::string> &headers,
+	unsigned int timeout,
+	void (*handler)(void *,int,const std::string &,bool,const std::string &),
+	void *arg)
+{
+	return (HttpClient::Request)(new P_Req(method,url,headers,timeout,handler,arg));
+}
+
+#endif
+
 } // namespace ZeroTier

+ 74 - 0
windows/SelfTest/SelfTest.vcxproj

@@ -18,6 +18,80 @@
       <Platform>x64</Platform>
     </ProjectConfiguration>
   </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\node\Address.hpp" />
+    <ClInclude Include="..\..\node\Array.hpp" />
+    <ClInclude Include="..\..\node\AtomicCounter.hpp" />
+    <ClInclude Include="..\..\node\BandwidthAccount.hpp" />
+    <ClInclude Include="..\..\node\Buffer.hpp" />
+    <ClInclude Include="..\..\node\C25519.hpp" />
+    <ClInclude Include="..\..\node\CertificateOfMembership.hpp" />
+    <ClInclude Include="..\..\node\CMWC4096.hpp" />
+    <ClInclude Include="..\..\node\Condition.hpp" />
+    <ClInclude Include="..\..\node\Constants.hpp" />
+    <ClInclude Include="..\..\node\Defaults.hpp" />
+    <ClInclude Include="..\..\node\Demarc.hpp" />
+    <ClInclude Include="..\..\node\Dictionary.hpp" />
+    <ClInclude Include="..\..\node\EthernetTap.hpp" />
+    <ClInclude Include="..\..\node\HttpClient.hpp" />
+    <ClInclude Include="..\..\node\Identity.hpp" />
+    <ClInclude Include="..\..\node\InetAddress.hpp" />
+    <ClInclude Include="..\..\node\Logger.hpp" />
+    <ClInclude Include="..\..\node\MAC.hpp" />
+    <ClInclude Include="..\..\node\Multicaster.hpp" />
+    <ClInclude Include="..\..\node\MulticastGroup.hpp" />
+    <ClInclude Include="..\..\node\Mutex.hpp" />
+    <ClInclude Include="..\..\node\Network.hpp" />
+    <ClInclude Include="..\..\node\NetworkConfig.hpp" />
+    <ClInclude Include="..\..\node\Node.hpp" />
+    <ClInclude Include="..\..\node\NodeConfig.hpp" />
+    <ClInclude Include="..\..\node\NonCopyable.hpp" />
+    <ClInclude Include="..\..\node\Packet.hpp" />
+    <ClInclude Include="..\..\node\PacketDecoder.hpp" />
+    <ClInclude Include="..\..\node\Peer.hpp" />
+    <ClInclude Include="..\..\node\Poly1305.hpp" />
+    <ClInclude Include="..\..\node\RuntimeEnvironment.hpp" />
+    <ClInclude Include="..\..\node\Salsa20.hpp" />
+    <ClInclude Include="..\..\node\Service.hpp" />
+    <ClInclude Include="..\..\node\SHA512.hpp" />
+    <ClInclude Include="..\..\node\SharedPtr.hpp" />
+    <ClInclude Include="..\..\node\SoftwareUpdater.hpp" />
+    <ClInclude Include="..\..\node\Switch.hpp" />
+    <ClInclude Include="..\..\node\SysEnv.hpp" />
+    <ClInclude Include="..\..\node\Thread.hpp" />
+    <ClInclude Include="..\..\node\Topology.hpp" />
+    <ClInclude Include="..\..\node\UdpSocket.hpp" />
+    <ClInclude Include="..\..\node\Utils.hpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\node\C25519.cpp" />
+    <ClCompile Include="..\..\node\CertificateOfMembership.cpp" />
+    <ClCompile Include="..\..\node\Defaults.cpp" />
+    <ClCompile Include="..\..\node\Demarc.cpp" />
+    <ClCompile Include="..\..\node\EthernetTap.cpp" />
+    <ClCompile Include="..\..\node\HttpClient.cpp" />
+    <ClCompile Include="..\..\node\Identity.cpp" />
+    <ClCompile Include="..\..\node\InetAddress.cpp" />
+    <ClCompile Include="..\..\node\Logger.cpp" />
+    <ClCompile Include="..\..\node\Multicaster.cpp" />
+    <ClCompile Include="..\..\node\Network.cpp" />
+    <ClCompile Include="..\..\node\NetworkConfig.cpp" />
+    <ClCompile Include="..\..\node\Node.cpp" />
+    <ClCompile Include="..\..\node\NodeConfig.cpp" />
+    <ClCompile Include="..\..\node\Packet.cpp" />
+    <ClCompile Include="..\..\node\PacketDecoder.cpp" />
+    <ClCompile Include="..\..\node\Peer.cpp" />
+    <ClCompile Include="..\..\node\Poly1305.cpp" />
+    <ClCompile Include="..\..\node\Salsa20.cpp" />
+    <ClCompile Include="..\..\node\Service.cpp" />
+    <ClCompile Include="..\..\node\SHA512.cpp" />
+    <ClCompile Include="..\..\node\SoftwareUpdater.cpp" />
+    <ClCompile Include="..\..\node\Switch.cpp" />
+    <ClCompile Include="..\..\node\SysEnv.cpp" />
+    <ClCompile Include="..\..\node\Topology.cpp" />
+    <ClCompile Include="..\..\node\UdpSocket.cpp" />
+    <ClCompile Include="..\..\node\Utils.cpp" />
+  </ItemGroup>
   <PropertyGroup Label="Globals">
     <ProjectGuid>{DCD73B97-0F44-4044-8BA4-95B59CCAB4BD}</ProjectGuid>
     <Keyword>Win32Proj</Keyword>

+ 214 - 0
windows/SelfTest/SelfTest.vcxproj.filters

@@ -10,4 +10,218 @@
       <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
     </Filter>
   </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\node\Address.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Array.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\AtomicCounter.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\BandwidthAccount.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Buffer.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\C25519.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\CertificateOfMembership.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\CMWC4096.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Condition.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Constants.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Defaults.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Demarc.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Dictionary.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\EthernetTap.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\HttpClient.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Identity.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\InetAddress.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Logger.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\MAC.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Multicaster.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\MulticastGroup.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Mutex.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Network.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\NetworkConfig.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Node.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\NodeConfig.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\NonCopyable.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Packet.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\PacketDecoder.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Peer.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Poly1305.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\RuntimeEnvironment.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Salsa20.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Service.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\SHA512.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\SharedPtr.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\SoftwareUpdater.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Switch.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\SysEnv.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Thread.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Topology.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\UdpSocket.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\node\Utils.hpp">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\node\C25519.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\CertificateOfMembership.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Defaults.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Demarc.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\EthernetTap.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\HttpClient.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Identity.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\InetAddress.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Logger.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Multicaster.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Network.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\NetworkConfig.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Node.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\NodeConfig.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Packet.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\PacketDecoder.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Peer.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Poly1305.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Salsa20.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Service.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\SHA512.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\SoftwareUpdater.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Switch.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\SysEnv.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Topology.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\UdpSocket.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\node\Utils.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+  </ItemGroup>
 </Project>