diff --git a/.vscode/settings.json b/.vscode/settings.json index 139d1ccbd2eef52af15b0e255b35be6ecf5daae7..528908f2d41471955b4275c0316f1feb008b628a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,14 @@ { "python.pythonPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\Python36_86\\python.exe", "git.ignoreLimitWarning": true, - "files.associations": {} + "files.associations": { + "array": "c", + "vector": "c", + "xstring": "c", + "xutility": "c", + "thread": "c", + "ostream": "c", + "system_error": "c", + "mutex": "c" + } } \ No newline at end of file diff --git a/3rd/libevent2.1.8.zip b/3rd/libevent2.1.8.zip new file mode 100644 index 0000000000000000000000000000000000000000..10421b8df6cb217fbdcfc931d1e9f01fc50b24de Binary files /dev/null and b/3rd/libevent2.1.8.zip differ diff --git a/3rd/libuv/libuv.vcxproj b/3rd/libuv/libuv.vcxproj deleted file mode 100644 index 71657bf5c608d9413c16393b9e6b646d5620ea1e..0000000000000000000000000000000000000000 --- a/3rd/libuv/libuv.vcxproj +++ /dev/null @@ -1,185 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - {33066374-88CB-CB8D-15DA-61032886329A} - Win32Proj - libuv - true - x64 - 10.0.16299.0 - - - - StaticLibrary - - - v141 - - - - - - - - - - $(ExecutablePath);$(MSBuildProjectDirectory)\.\bin\;$(MSBuildProjectDirectory)\.\bin\ - $(Configuration)\obj\$(ProjectName)\ - false - true - $(SolutionDir)$(Configuration)\ - $(ProjectName) - $(OutDir)lib\$(ProjectName)$(TargetExt) - - - - include;src;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - EnableFastChecks - true - ProgramDatabase - Sync - false - false - Disabled - NotUsing - WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LARGEFILE_SOURCE;_FILE_OFFSET_BITS=64;_WIN32_WINNT=0x0600;_GNU_SOURCE;DEBUG;_DEBUG;%(PreprocessorDefinitions) - MultiThreadedDebugDLL - true - true - false - Level3 - $(OutDir)obj\$(ProjectName).pdb - - - $(OutDir)$(ProjectName)$(TargetExt) - - - - - true - true - true - true - true - - - include;src;%(AdditionalIncludeDirectories) - WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LARGEFILE_SOURCE;_FILE_OFFSET_BITS=64;_WIN32_WINNT=0x0600;_GNU_SOURCE;DEBUG;_DEBUG;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - - - include;src;%(AdditionalIncludeDirectories) - /MP %(AdditionalOptions) - true - ProgramDatabase - Sync - Speed - true - AnySuitable - true - true - Full - NotUsing - WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LARGEFILE_SOURCE;_FILE_OFFSET_BITS=64;_WIN32_WINNT=0x0600;_GNU_SOURCE;NDEBUG;%(PreprocessorDefinitions) - MultiThreadedDLL - true - true - false - Level3 - true - $(OutDir)obj\$(ProjectName).pdb - - - /LTCG %(AdditionalOptions) - $(OutDir)$(ProjectName)$(TargetExt) - - - - - true - true - true - true - UseLinkTimeCodeGeneration - true - true - true - - - include;src;%(AdditionalIncludeDirectories) - WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_LARGEFILE_SOURCE;_FILE_OFFSET_BITS=64;_WIN32_WINNT=0x0600;_GNU_SOURCE;NDEBUG;%(PreprocessorDefinitions);%(PreprocessorDefinitions) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/3rd/make3rdcompile.sh b/3rd/make3rdcompile.sh index 87335c884a9e35c3c8e4a6adcf93e9918139f186..7655298e5c046b9a25213226fe2922da147e577c 100644 --- a/3rd/make3rdcompile.sh +++ b/3rd/make3rdcompile.sh @@ -5,7 +5,6 @@ # Created Time: Sun 07 Jan 2018 02:54:11 AM DST ######################################################################### function getlibuv(){ - cd libuv ./configure --enable-static --disable-shared --prefix=/opt/local/ make -j diff --git a/CMakeLists.txt b/CMakeLists.txt index efed329620a35bcac146d91d858f328d6d1011d3..410f74a3e2945ca4e01d94087a6353b48aab5368 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,8 +42,6 @@ add_subdirectory(comenv) add_subdirectory(infoanalysis) add_subdirectory(asynio) add_subdirectory(sshchannel) -#add_subdirectory(adapterjs) -#add_subdirectory(adapterlua) -#add_subdirectory(adapterpy) +add_subdirectory(protocol) #add_subdirectory(mempool) #add_subdirectory(adapters) diff --git a/asynio/CMakeLists.txt b/asynio/CMakeLists.txt index bd32b4162fd0ce35cec66ac0f6bb6952aa0138a7..56c74ba0cd3cade3da33c0c756236e380f177891 100644 --- a/asynio/CMakeLists.txt +++ b/asynio/CMakeLists.txt @@ -3,11 +3,13 @@ cmake_minimum_required(VERSION 2.8) set(asynio_src dllmain.cpp filereadimpl.cpp filewriteimpl.cpp - asynioimpl.cpp + asynframeimpl.cpp + asynctcpsocketimpl.cpp tcpsocketimpl.cpp - impl/sys_file.cpp - impl/fileop.cpp) - + iooperationimpl.cpp) + + +file(GLOB iouv_src "ioimpl/*.cpp") if (${UNIX_OS}) include_directories( @@ -30,11 +32,11 @@ endif() set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) -add_library(asynio SHARED ${asynio_src}) +add_library(asynio SHARED ${asynio_src} ${iouv_src}) set_target_properties(asynio PROPERTIES OUTPUT_NAME "asynio") -set_target_properties(asynio PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -fPIC -std=c++11 -frtti -Wall -Werror -fexceptions") +set_target_properties(asynio PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -fPIC -Wl,--no-as-needed -std=c++11 -frtti -Wall -Werror -fexceptions") if(CMAKE_BUILD_TYPE STREQUAL Debug) set_target_properties(asynio PROPERTIES COMPILE_FLAGS "-g3") @@ -45,6 +47,7 @@ if(CMAKE_BUILD_TYPE STREQUAL Release) endif() target_link_libraries(asynio dl) +target_link_libraries(asynio pthread) target_link_libraries(asynio libuv.a) install(TARGETS asynio diff --git a/asynio/asynctcpsocketimpl.cpp b/asynio/asynctcpsocketimpl.cpp index f6960580c5e3a0fd471c07c412af942cef59d034..7d98867970aa988209486839ff9d661cbffa3456 100644 --- a/asynio/asynctcpsocketimpl.cpp +++ b/asynio/asynctcpsocketimpl.cpp @@ -1,8 +1,17 @@ #include "asynctcpsocketimpl.h" +#include "iooperationimpl.h" +#include "ioimpl/iothreadpool.h" + +struct PostData { + io_tcp_i* tcp; + IIoOperation* pOperation; +}; CAsyncTcpSocketImpl::CAsyncTcpSocketImpl() { - m_socketFd = -1; + m_tcp = new io_tcp_i; + memset(m_tcp, 0, sizeof(io_tcp_i)); + } CAsyncTcpSocketImpl::~CAsyncTcpSocketImpl() { @@ -33,51 +42,58 @@ std_method_impl CAsyncTcpSocketImpl::WriteAllIo(IIoOperation* pOperation) return hr; } -std_method_impl CAsyncTcpSocketImpl::CloseIo() +std_method_impl CAsyncTcpSocketImpl::ConnectIo(IIoOperation* pOperation) { HRESULT hr = S_OK; - return hr; + m_tcp->data = static_cast(pOperation); + pOperation->SetOpType(OP_TCPSOCKET_CONNECT); + int ires = post_io_threadpool(NULL,pOperation, CAsyncTcpSocketImpl::WokerProc); + + return ires == 1 ? S_OK : E_FAIL; } -std_method_impl CAsyncTcpSocketImpl::OpenIo() +std_method_impl CAsyncTcpSocketImpl::AcceptConnect(IIoOperation* pOperation) { HRESULT hr = S_OK; - m_socketFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - - if (m_socketFd == INVALID_SOCKET) { - return E_FAIL; - } return hr; } -std_method_type_impl(os_sock_t) CAsyncTcpSocketImpl::GetSocket() +std_method_impl CAsyncTcpSocketImpl::CloseIo() { - return m_socketFd; -} + HRESULT hr = S_OK; + +#if (TARGET_OS == OS_WINDOWS) + closesocket(m_socketFd); +#elif (TARGET_OS == OS_POSIX) + close(m_socketFd); +#endif + io_tcp_uninit(m_tcp); -std_method_impl CAsyncTcpSocketImpl::Bind(const char* addr, unsigned int uport) + return hr; +} +std_method_impl CAsyncTcpSocketImpl::OpenIo() { HRESULT hr = S_OK; - retrtpv(addr, E_FAIL) - retrtpv(uport, E_FAIL) + + m_socketFd = -1; + //m_tcp = io_tcp_init(); + - struct sockaddr_in sin; - sin.sin_family = AF_INET; - if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(addr))) { - return E_FAIL; - } - sin.sin_port = htons(uport); - if (connect(m_socketFd, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { + m_socketFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + + if (m_socketFd == INVALID_SOCKET) { return E_FAIL; } + //io_tcp_open(m_tcp,m_socketFd); + return hr; } -std_method_type_impl(os_sock_t) CAsyncTcpSocketImpl::BindAccept(const char* addr, unsigned int uport, int n) +std_method_type_impl(os_sock_t) CAsyncTcpSocketImpl::GetSocket() { - return -1; + return m_socketFd; } std_method_impl CAsyncTcpSocketImpl::SetReuseAddr(bool bstart) { @@ -166,4 +182,16 @@ std_method_impl CAsyncTcpSocketImpl::RecvLoWat(int size) return S_OK; } +void CAsyncTcpSocketImpl::WokerProc(void* pData) +{ + CIoOperationImpl* pThis = static_cast(pData); + + /* + char log[64] = { 0x00 }; + sprintf(log, "thread id %lu\n", GetCurrentThreadId()); + OutputDebugStringA(log); + */ + + pThis->m_pEvent->OnOperationComplete(pThis); +} diff --git a/asynio/asynctcpsocketimpl.h b/asynio/asynctcpsocketimpl.h index 53ef82c122a55ffe73016552bdf7641ab198d611..8c01f47386e39f93e44dd45092fafe87261c932f 100644 --- a/asynio/asynctcpsocketimpl.h +++ b/asynio/asynctcpsocketimpl.h @@ -4,9 +4,11 @@ #include "stdafx.h" #include +#include "ioimpl/iotcpbase.h" +uvNameSpace + class CAsyncTcpSocketImpl : public IAsyncTcpSocket, public CUnknownImp - { public: CAsyncTcpSocketImpl(void); @@ -18,6 +20,8 @@ public: std_method(WriteIo)(IIoOperation* pOperation); std_method(ReadAllIo)(IIoOperation* pOperation); std_method(WriteAllIo)(IIoOperation* pOperation); + std_method(ConnectIo)(IIoOperation* pOperation); + std_method(AcceptConnect)(IIoOperation* pOperation); std_method(CloseIo)(); std_method(OpenIo)(); ////////////////////////////////////////////////////////////////////////// @@ -25,16 +29,12 @@ public: std_method_(os_sock_t, GetSocket)(); ////////////////////////////////////////////////////////////////////////// //ITcpSocket - std_method(Bind)(const char* addr, unsigned int uport); - std_method_(os_sock_t, BindAccept)(const char* addr, unsigned int uport, int n); std_method(SetReuseAddr)(bool bstart); std_method(SetNoDelay)(bool bstart); std_method(SetLinger)(bool bstart); std_method(SetKeepalive)(bool bstart); std_method(SetCork)(bool bstart); std_method(SetNoSigPipe)(bool bstart); - ////////////////////////////////////////////////////////////////////////// - //IAsynTcpSocket std_method(SetNonblock)(bool bstart); std_method(SendBufLen)(int size); std_method(RecvBufLen)(int size); @@ -43,10 +43,12 @@ public: std_method(SendLoWat)(int size); std_method(RecvLoWat)(int size); ////////////////////////////////////////////////////////////////////////// + //IAsynTcpSocket + ////////////////////////////////////////////////////////////////////////// os_sock_t m_socketFd; - + io_tcp_i* m_tcp; private: - + static void WokerProc(void* pData); }; diff --git a/asynio/asynframeimpl.cpp b/asynio/asynframeimpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d8a4d41940bf4b276933af895ed2f2fb906e3a6 --- /dev/null +++ b/asynio/asynframeimpl.cpp @@ -0,0 +1,174 @@ +#include "asynframeimpl.h" + +#include "filereadimpl.h" +#include "filewriteimpl.h" +#include "tcpsocketimpl.h" +#include "asynctcpsocketimpl.h" + + +uvNameSpace + +CAsynFrameImpl::CAsynFrameImpl(void) +{ + m_startService = false; +} + +CAsynFrameImpl::~CAsynFrameImpl(void) +{ +} +////////////////////////////////////////////////////////////////////////// +std_method_impl CAsynFrameImpl::init_class(IBase* prot, IBase* punkOuter) +{ + HRESULT hr = S_OK; + if (prot != NULL) + { + m_pRot = prot; + } + return hr; +} +std_method_impl CAsynFrameImpl::Init(void*) +{ + return S_OK; +} +std_method_impl CAsynFrameImpl::Uninit() +{ + return S_OK; +} +std_method_impl CAsynFrameImpl::Start() +{ +#if (TARGET_OS == OS_WINDOWS) + WORD verision = MAKEWORD(2, 2); + WSADATA lpData; + int intEr = WSAStartup(verision, &lpData); + if (intEr != 0) + { + return E_FAIL; + } +#endif + + m_pThreadPool = new io_thread_pool; + + + ithread::start_thread(); + + while (!m_startService) { + + } + return S_OK; +} +std_method_impl CAsynFrameImpl::Stop() +{ + +#if (TARGET_OS == OS_WINDOWS) + + if (WSACleanup() != 0) + { + return E_FAIL; + } +#endif + return S_OK; +} +std_method_impl CAsynFrameImpl::AddTimer(ITimerEvents *pEvents, + ULONG lTimerId, + ULONG lMilliSecond, + BOOL bCycled) +{ + return S_OK; +} +std_method_impl CAsynFrameImpl::DelTimer(ITimerEvents *pEvents, ULONG lTimerId) +{ + return S_OK; +} +std_method_impl CAsynFrameImpl::ClearTimer(ITimerEvents *pEvents) +{ + return S_OK; +} +std_method_impl CAsynFrameImpl::CreateAsynIoOperation( IIoOperation **ppOperation, + IIoOperationEvents* pEvent) +{ + CIoOperationImpl* Oper = NULL; + Oper = new CIoOperationImpl; + Oper->BindEvent(pEvent); + return Oper->QueryInterface(_uuidof(IIoOperation), (void**)ppOperation); +} +std_method_impl CAsynFrameImpl::PostAsynIoOperation(IIoOperation *pOperation) +{ + int ires = post_io_threadpool(m_pThreadPool,pOperation, CAsynFrameImpl::WokerProc); + return ires == 1 ? S_OK : E_FAIL; +} +std_method_impl CAsynFrameImpl::CreateReadFile(IBase** pReadFile) +{ + CFileReadImpl* pObject = NULL; + pObject = new CFileReadImpl; + return pObject->QueryInterface(_uuidof(IReadFile), (void**)pReadFile);; +} +std_method_impl CAsynFrameImpl::CreateWriteFile(IBase** pWriteFile) +{ + CFileWriteImpl* pObject = NULL; + pObject = new CFileWriteImpl; + return pObject->QueryInterface(_uuidof(IWriteFile), (void**)pWriteFile); +} +std_method_impl CAsynFrameImpl::CreateAsyncTcpSocket(IBase** pAsynTcpSocket) +{ + CAsyncTcpSocketImpl* pObject = NULL; + pObject = new CAsyncTcpSocketImpl; + return pObject->QueryInterface(_uuidof(IAsyncTcpSocket), (void**)pAsynTcpSocket); +} +std_method_impl CAsynFrameImpl::CreateTcpSocket(IBase** pTcpSocket) +{ + CTcpSocketImpl* pObject = NULL; + pObject = new CTcpSocketImpl; + return pObject->QueryInterface(_uuidof(ITcpSocket), (void**)pTcpSocket); +} +std_method_impl CAsynFrameImpl::CreateAsyncUdpSocket(IBase** pAsynUdpSocket) +{ + HRESULT hr = S_OK; + return hr; +} +std_method_impl CAsynFrameImpl::CreateUdpSocket(IBase** pUdpSocket) +{ + HRESULT hr = S_OK; + return hr; +} + +std_method_impl CAsynFrameImpl::DeleteIo(IBase* pAsynIo) +{ + HRESULT hr = S_OK; + if (pAsynIo != NULL) + { + pAsynIo->Release(); + } + return hr; +} +void CAsynFrameImpl::run() +{ + init_threadpool(m_pThreadPool,std::thread::hardware_concurrency(), std::thread::hardware_concurrency(),this); + //instance_threadpool(1,1,this); + setoncethreadspool(m_pThreadPool); + run_threadpool(m_pThreadPool,CAsynFrameImpl::StartCBFun, CAsynFrameImpl::StopCBFun); +} +void CAsynFrameImpl::threadstop() +{ + +} +void CAsynFrameImpl::Setservice(bool bstart) +{ + m_startService = bstart; + +} +void CAsynFrameImpl::StartCBFun(void *pData) +{ + CAsynFrameImpl* pThis = static_cast(pData); + pThis->Setservice(true); + +} +void CAsynFrameImpl::StopCBFun(void *pData) +{ + +} +void CAsynFrameImpl::WokerProc(void* pData) +{ + CIoOperationImpl* pThis = static_cast(pData); + + pThis->m_pEvent->OnOperationComplete(pThis); +} diff --git a/asynio/ioeventbaseimpl.h b/asynio/asynframeimpl.h similarity index 49% rename from asynio/ioeventbaseimpl.h rename to asynio/asynframeimpl.h index 730d51fe9fb20c1cd7cb32a863dfc16b6e40f41f..c5c9789cff21729b07e679fc8dbca12ce5095432 100644 --- a/asynio/ioeventbaseimpl.h +++ b/asynio/asynframeimpl.h @@ -2,18 +2,30 @@ #define _IOEVENTBASE_H_ #include "stdafx.h" -#include +#include +#include -class CEventBaseImpl : public IEventBase, + +#include "ioimpl/iothreadpool.h" + +#include "iooperationimpl.h" + +uvNameSpace + +#define OP_ID 1000 + +class CAsynFrameImpl : public IAsynFrame, + public IAsynIo, public IPlugin, public IPluginRun, - public CUnknownImp + public CUnknownImp, + public ithread { public: - CEventBaseImpl(void); - virtual ~CEventBaseImpl(void); + CAsynFrameImpl(void); + virtual ~CAsynFrameImpl(void); - UNKNOWN_IMP3_(IPlugin, IPluginRun, IEventBase); + UNKNOWN_IMP4_(IPlugin, IPluginRun, IAsynFrame, IAsynIo); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -29,34 +41,43 @@ public: std_method(Start)(); std_method(Stop)(); ////////////////////////////////////////////////////////////////////////// - + //IAsynFrame ////////////////////////////////////////////////////////////////////////// - std_method(AttachMessageEvents)(IMessageEvents *pEvents); - std_method(DetachMessageEvents)(IMessageEvents *pEvents); - std_method(SendMessage)(IMessageEvents *pEvents, - ULONG lMessageId, - ULONG lParam1, - ULONG lParam2); - std_method(PostMessage)(IMessageEvents *pEvents, - ULONG lMessageId, - ULONG lParam1, - ULONG lParam2); std_method(AddTimer)(ITimerEvents *pEvents, ULONG lTimerId, ULONG lMilliSecond, BOOL bCycled); std_method(DelTimer)(ITimerEvents *pEvents, ULONG lTimerId); std_method(ClearTimer)(ITimerEvents *pEvents); - std_method(CreateAsynIoOperation)(IIoOperation **ppOperation); + std_method(CreateAsynIoOperation)( IIoOperation **ppOperation, + IIoOperationEvents* pEvent); std_method(PostAsynIoOperation)(IIoOperation *pOperation); - ////////////////////////////////////////////////////////////////////////// + //IAsynIo + std_method(CreateReadFile)(IBase** pReadFile); + std_method(CreateWriteFile)(IBase** pWriteFile); + std_method(CreateAsyncTcpSocket)(IBase** pAsynTcpSocket); + std_method(CreateTcpSocket)(IBase** pTcpSocket); + std_method(CreateAsyncUdpSocket)(IBase** pAsynUdpSocket); + std_method(CreateUdpSocket)(IBase** pUdpSocket); + std_method(DeleteIo)(IBase* pAsynIo); + ////////////////////////////////////////////////////////////////////////// +protected: + void run(); + void threadstop(); + void Setservice(bool bstart); + private: - _lComPtr m_pRot; - - - + static void WokerProc(void* pData); + static void StartCBFun(void *pData); + static void StopCBFun(void *pData); +private: + _lComPtr m_pRot; + CAutoCriticalSection m_OperQueuMutex; +private: + bool m_startService; + io_thread_pool* m_pThreadPool; }; #endif \ No newline at end of file diff --git a/asynio/asynio.vcxproj b/asynio/asynio.vcxproj index 8b9e3b1b564706f664c414ce54a9dd47b59ffc96..da6c024dca5b4f5643f729d15851f6ed50884807 100644 --- a/asynio/asynio.vcxproj +++ b/asynio/asynio.vcxproj @@ -105,8 +105,8 @@ + - @@ -117,13 +117,23 @@ - - - - + + + + + + + + + + + + + + + + - - @@ -131,17 +141,30 @@ - + - - - - - + + + + + + + + + + + + + + + + + + + + - - diff --git a/asynio/asynioimpl.cpp b/asynio/asynioimpl.cpp deleted file mode 100644 index 8d82dce8d1ceaf0573fab15680606fc46bd64c74..0000000000000000000000000000000000000000 --- a/asynio/asynioimpl.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "asynioimpl.h" -#include "filereadimpl.h" -#include "filewriteimpl.h" -#include "tcpsocketimpl.h" -#include "asynctcpsocketimpl.h" - -CAsynIoImpl::CAsynIoImpl(void) -{ -} - -CAsynIoImpl::~CAsynIoImpl(void) -{ -} -////////////////////////////////////////////////////////////////////////// -std_method_impl CAsynIoImpl::init_class(IBase* prot, IBase* punkOuter) -{ - HRESULT hr = S_OK; - if (prot != NULL) - { - m_pRot = prot; - } - return hr; -} -std_method_impl CAsynIoImpl::Init(void*) -{ - HRESULT hr = S_OK; - - return hr; -} -std_method_impl CAsynIoImpl::Uninit() -{ - HRESULT hr = S_OK; - - return hr; -} -std_method_impl CAsynIoImpl::Start() -{ - HRESULT hr = S_OK; - - return hr; -} -std_method_impl CAsynIoImpl::Stop() -{ - HRESULT hr = S_OK; - return hr; -} -std_method_impl CAsynIoImpl::CreateReadFile(IBase** pReadFile) -{ - CFileReadImpl* pObject = NULL; - pObject = new CFileReadImpl; - return pObject->QueryInterface(_uuidof(IReadFile), (void**)pReadFile);; -} -std_method_impl CAsynIoImpl::CreateWriteFile(IBase** pWriteFile) -{ - CFileWriteImpl* pObject = NULL; - pObject = new CFileWriteImpl; - return pObject->QueryInterface(_uuidof(IWriteFile), (void**)pWriteFile); -} -std_method_impl CAsynIoImpl::CreateAsyncTcpSocket(IBase** pAsynTcpSocket) -{ - CAsyncTcpSocketImpl* pObject = NULL; - pObject = new CAsyncTcpSocketImpl; - return pObject->QueryInterface(_uuidof(IAsyncTcpSocket), (void**)pAsynTcpSocket); -} -std_method_impl CAsynIoImpl::CreateTcpSocket(IBase** pTcpSocket) -{ - CTcpSocketImpl* pObject = NULL; - pObject = new CTcpSocketImpl; - return pObject->QueryInterface(_uuidof(ITcpSocket), (void**)pTcpSocket); -} -std_method_impl CAsynIoImpl::CreateAsyncUdpSocket(IBase** pAsynUdpSocket) -{ - HRESULT hr = S_OK; - return hr; -} -std_method_impl CAsynIoImpl::CreateUdpSocket(IBase** pUdpSocket) -{ - HRESULT hr = S_OK; - return hr; -} - -std_method_impl CAsynIoImpl::DeleteIo(IBase* pAsynIo) -{ - HRESULT hr = S_OK; - if (pAsynIo != NULL) - { - pAsynIo->Release(); - } - return hr; -} diff --git a/asynio/dllmain.cpp b/asynio/dllmain.cpp index a5febf90eef41066bf0e758e41013b3df9beb03a..f3e8a0332c60086aedec52d66af4a21b942d6023 100644 --- a/asynio/dllmain.cpp +++ b/asynio/dllmain.cpp @@ -1,6 +1,6 @@ // dllmain.cpp : Defines the entry point for the DLL application. #include "stdafx.h" -#include "asynioimpl.h" +#include "asynframeimpl.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved @@ -20,7 +20,7 @@ BOOL APIENTRY DllMain( HMODULE hModule, BEGIN_CLIDMAP CLIDMAPENTRY_BEGIN - CLIDMAPENTRY_PROGID(CLSID_IAsynIo, CAsynIoImpl,"AsynIo.Impl") + CLIDMAPENTRY_PROGID(CLSID_IAsynFrame, CAsynFrameImpl, "AsynFrame.Impl") CLIDMAPENTRY_END END_CLIDMAP_AND_EXPORTFUN MD_EXPORTS DllCanUnloadNow(void) diff --git a/asynio/filereadimpl.h b/asynio/filereadimpl.h index b24728dcca52e13be4a29843096b40d2bb4f6c8e..ec0defabdf0a268a356aaa98f13d6116dfe8f482 100644 --- a/asynio/filereadimpl.h +++ b/asynio/filereadimpl.h @@ -5,7 +5,7 @@ #include #include -#include "impl/fileop.h" +#include "ioimpl/file.h" class CFileReadImpl : public IReadFile, public CUnknownImp diff --git a/asynio/ioeventbaseimpl.cpp b/asynio/ioeventbaseimpl.cpp deleted file mode 100644 index 1b8842d6ae07296e28dcecf6fc1ef72e418d2b84..0000000000000000000000000000000000000000 --- a/asynio/ioeventbaseimpl.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "ioeventbaseimpl.h" -#include "iooperationimpl.h" - -CEventBaseImpl::CEventBaseImpl(void) -{ -} - -CEventBaseImpl::~CEventBaseImpl(void) -{ -} -////////////////////////////////////////////////////////////////////////// -std_method_impl CEventBaseImpl::init_class(IBase* prot, IBase* punkOuter) -{ - HRESULT hr = S_OK; - if (prot != NULL) - { - m_pRot = prot; - } - return hr; -} -std_method_impl CEventBaseImpl::Init(void*) -{ - return S_OK; -} -std_method_impl CEventBaseImpl::Uninit() -{ - return S_OK; -} -std_method_impl CEventBaseImpl::Start() -{ - return S_OK; -} -std_method_impl CEventBaseImpl::Stop() -{ - return S_OK; -} - -std_method_impl CEventBaseImpl::AttachMessageEvents(IMessageEvents *pEvents) -{ - return S_OK; -} -std_method_impl CEventBaseImpl::DetachMessageEvents(IMessageEvents *pEvents) -{ - return S_OK; -} -std_method_impl CEventBaseImpl::SendMessage(IMessageEvents *pEvents, - ULONG lMessageId, - ULONG lParam1, - ULONG lParam2) -{ - return S_OK; -} -std_method_impl CEventBaseImpl::PostMessage(IMessageEvents *pEvents, - ULONG lMessageId, - ULONG lParam1, - ULONG lParam2) -{ - return S_OK; -} -std_method_impl CEventBaseImpl::AddTimer(ITimerEvents *pEvents, - ULONG lTimerId, - ULONG lMilliSecond, - BOOL bCycled) -{ - return S_OK; -} -std_method_impl CEventBaseImpl::DelTimer(ITimerEvents *pEvents, ULONG lTimerId) -{ - return S_OK; -} -std_method_impl CEventBaseImpl::ClearTimer(ITimerEvents *pEvents) -{ - return S_OK; -} -std_method_impl CEventBaseImpl::CreateAsynIoOperation(IIoOperation **ppOperation) -{ - - CIoOperationImpl* Oper = NULL; - - Oper = new CIoOperationImpl; - - - - return S_OK; -} -std_method_impl CEventBaseImpl::PostAsynIoOperation(IIoOperation *pOperation) -{ - return S_OK; -} - diff --git a/asynio/ioeventdef.h b/asynio/ioeventdef.h deleted file mode 100644 index b7f34350c876d8f13147f9a0a3b473f8f2d13601..0000000000000000000000000000000000000000 --- a/asynio/ioeventdef.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef _IOEVENTDEF_H_ -#define _IOEVENTDEF_H_ - - -#include "stdafx.h" -#include - -template -struct evptr -{ -public: - evptr(const _Traits& tr = _Traits()) : m_tr(tr) - { - m_p = (_Ptr)m_tr.default_value(); - } - evptr(_Ptr p, const _Traits& tr = _Traits()) : m_p(p), m_tr(tr) - { - - } - ~evptr() - { - m_tr.destroy(m_p); - } - evptr& operator = (_Ptr p) - { - if (!m_tr.equal_to(m_p, p)) - { - m_tr.destroy(m_p); m_p = p; - } - return *this; - } - - void dispose() - { - m_tr.destroy(m_p); - m_p = (_Ptr)m_tr.default_value(); - } - operator _Ptr () const - { - return m_p; - } - _Ptr operator -> () const - { - return m_p; - } - - _Ptr ptr() - { - return m_p; - } - const _Ptr ptr() const - { - return m_p; - } - -public: - _Ptr m_p; - _Traits m_tr; -private: - evptr(const evptr&); - evptr& operator = (const evptr&); -}; - -struct uv_loop_handler -{ - static uv_loop_t* default_value() { - return uv_loop_new(); - - } - template static bool equal_to(_Ptr l, _Ptr r) { - return l == r; - } - template static void destroy(_Ptr p) { - if (p != NULL) - { - uv_loop_delete(p); - p = NULL; - } - } -}; - -#endif // _IOEVENTDEF_H_ - diff --git a/asynio/ioeventloop.cpp b/asynio/ioeventloop.cpp deleted file mode 100644 index 561486dc4e8161756d2934e8cfd376ad0c1f3fe9..0000000000000000000000000000000000000000 --- a/asynio/ioeventloop.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "ioeventloop.h" - diff --git a/asynio/ioeventloop.h b/asynio/ioeventloop.h deleted file mode 100644 index 35b3967454c35459c8fb648e4cdf62c4696c7324..0000000000000000000000000000000000000000 --- a/asynio/ioeventloop.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef _IOEVENTLOOP_H_ -#define _IOEVENTLOOP_H_ - -#include "ioeventdef.h" -#include - -class ioeventloop : CSingletion -{ -public: - ioeventloop() { - - } - virtual ~ioeventloop() { - - } - - static ioeventloop* Getioeventloop() { - return CSingletion::GetInstance(); - } - -public: - uv_loop_t* GetEv() { - return uvloopbase; - } - - int DoRun() { - return uv_run(GetEv(), UV_RUN_DEFAULT); - } - int DoOnceRun() { - return uv_run(GetEv(), UV_RUN_ONCE); - } - int DoWaitRun() { - return uv_run(GetEv(), UV_RUN_NOWAIT); - } - int DoClose() { - uv_stop(GetEv()); - } - -protected: - evptr uvloopbase; -}; - - - - -class io_buff_t { -public: - io_buff_t() { - - } - virtual ~io_buff_t() { - - } - int MemAlloc(int size) { - buf.base= (char*)malloc(sizeof(char) * size + 1); - buf.len = size; - } - int MemRealloc(int size) { - buf.base = (char*)realloc(buf.base,sizeof(char) * size + 1); - buf.len = size; - } - int MemFree() { - free(buf.base); - } - operator void* () const { - return buf.base; - } - int len() { - return buf.len; - } -private: - uv_buf_t buf; -}; - - - -#endif \ No newline at end of file diff --git a/asynio/impl/fileop.cpp b/asynio/ioimpl/file.cpp similarity index 84% rename from asynio/impl/fileop.cpp rename to asynio/ioimpl/file.cpp index 712442f2a9745c9b4b4baea12420d68ea14ce3aa..34b2e85acf40c1d8e547ca2aee7d1f2d90958022 100644 --- a/asynio/impl/fileop.cpp +++ b/asynio/ioimpl/file.cpp @@ -1,5 +1,5 @@ -#include "fileop.h" -#include "sys_file.h" +#include "file.h" +#include "implfile.h" void loadFileInstance(FileImpl* fileop) { fileop->Open = os_file_open; @@ -8,7 +8,6 @@ void loadFileInstance(FileImpl* fileop) { fileop->Write = os_file_write; fileop->Seek = os_file_lseek; fileop->fSize = os_file_fsize; - } diff --git a/asynio/impl/fileop.h b/asynio/ioimpl/file.h similarity index 100% rename from asynio/impl/fileop.h rename to asynio/ioimpl/file.h diff --git a/asynio/impl/sys_file.cpp b/asynio/ioimpl/implfile.cpp similarity index 99% rename from asynio/impl/sys_file.cpp rename to asynio/ioimpl/implfile.cpp index 4f75baa42677d4b177233f31d0f0560a02496960..c2ed155478eb539ce4760c31704413969a5a0285 100644 --- a/asynio/impl/sys_file.cpp +++ b/asynio/ioimpl/implfile.cpp @@ -1,4 +1,4 @@ -#include "sys_file.h" +#include "implfile.h" #ifdef _MSC_VER os_fd_t os_file_open(const TCHAR *filepath, int flags, int mode) diff --git a/asynio/impl/sys_file.h b/asynio/ioimpl/implfile.h similarity index 100% rename from asynio/impl/sys_file.h rename to asynio/ioimpl/implfile.h diff --git a/asynio/ioimpl/ioallocator.cpp b/asynio/ioimpl/ioallocator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5684f5589e877bd8f8245861deaadf9e1d66a50d --- /dev/null +++ b/asynio/ioimpl/ioallocator.cpp @@ -0,0 +1,42 @@ +#include "ioallocator.h" + + + +#include +#include +#include + + +void* iouv_malloc_func(size_t size) { + + void* p = malloc(size); + return p; +} + +void* iouv_realloc_func(void* ptr, size_t size) { + + void* p = realloc(ptr,size); + return p; +} +void* iouv_calloc_func(size_t count, size_t size) { + + void* p = calloc(count, size); + return p; +} +void iouv_free_func(void* ptr) { + + if (ptr != NULL) + free(ptr); +} +int io_allocator(io_malloc_func malloc_func, + io_realloc_func realloc_func, + io_calloc_func calloc_func, + io_free_func free_func) { + + if (malloc_func == NULL || realloc_func == NULL || + calloc_func == NULL || free_func == NULL) { + return UV_EINVAL; + } + return uv_replace_allocator(malloc_func, realloc_func, calloc_func, free_func); +} + diff --git a/asynio/ioimpl/ioallocator.h b/asynio/ioimpl/ioallocator.h new file mode 100644 index 0000000000000000000000000000000000000000..9ac451d8a16fad3f3691d0bd555aca455ee15479 --- /dev/null +++ b/asynio/ioimpl/ioallocator.h @@ -0,0 +1,23 @@ +#ifndef _IOMSGFRAMING_H +#define _IOMSGFRAMING_H + +#include + +typedef uv_malloc_func io_malloc_func; +typedef uv_realloc_func io_realloc_func; +typedef uv_calloc_func io_calloc_func; +typedef uv_free_func io_free_func; + +void* iouv_malloc_func(size_t size); +void* iouv_realloc_func(void* ptr, size_t size); +void* iouv_calloc_func(size_t count, size_t size); +void iouv_free_func(void* ptr); + +int io_allocator( io_malloc_func malloc_func, + io_realloc_func realloc_func, + io_calloc_func calloc_func, + io_free_func free_func); + + + +#endif diff --git a/asynio/ioimpl/ioasyn.cpp b/asynio/ioimpl/ioasyn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f162b63fb33076992266f2dc3ecf4d09a349795f --- /dev/null +++ b/asynio/ioimpl/ioasyn.cpp @@ -0,0 +1,65 @@ +#include "ioasyn.h" + +uvNameSpaceBegin + +//////////////////////////////////////////////////////////////////////////////////////// +static void async_callback_close(uv_handle_t* handle) { + + io_asyn_t* p = (io_asyn_t*)(handle->data); + uv_unref((uv_handle_t*)&p->asyndata); + iouv_free_func(p); +}; + +static void async_callback(uv_async_t* handle) { + + io_asyn_t* p = (io_asyn_t*)(handle->data); + + p->io.uRecvId = (int)uv_thread_self(); + + char log[64] = { 0x00 }; + sprintf(log, "send thread id:%d recv thread id %d \n", p->io.uSendId, p->io.uRecvId); + iosprintf(log); + + + p->io.func(p->io.pdata); + uv_unref((uv_handle_t*)handle); + uv_close((uv_handle_t*)handle,async_callback_close); +} +int do_async_send(uv_loop_t* eventloop, async_fun_cb func, async_fun_cb freefunc, void* pThis) { + + io_asyn_t* async = (io_asyn_t*)iouv_malloc_func(sizeof(io_asyn_t)); + async->asyndata.data = async; + async->io.pdata = pThis; + async->io.func = func; + async->io.freefunc = freefunc; + async->io.uSendId = (int)uv_thread_self(); + uv_async_init(eventloop, &async->asyndata, async_callback); + uv_ref((uv_handle_t*)&async->asyndata); + uv_async_send(&async->asyndata); + + + return 1; +} +//////////////////////////////////////////////////////////////////////////////////////// + +static void async_io_callback_close(uv_handle_t* handle) { + + io_asyn_t* p = (io_asyn_t*)(handle->data); + p->io.freefunc(p); +}; +static void asyn_io_callback(uv_async_t* handle) { + + io_asyn_t* p = (io_asyn_t*)(handle->data); + p->io.func(p->io.pdata); + uv_close((uv_handle_t*)handle, async_io_callback_close); +} + +int do_async_io_send(uv_loop_t* eventloop, io_asyn_t* p) { + + p->asyndata.data = p; + uv_async_init(eventloop, &p->asyndata, asyn_io_callback); + uv_async_send(&p->asyndata); + return 1; +} +//////////////////////////////////////////////////////////////////////////////////////// +uvNameSpaceEnd \ No newline at end of file diff --git a/asynio/ioimpl/ioasyn.h b/asynio/ioimpl/ioasyn.h new file mode 100644 index 0000000000000000000000000000000000000000..d6cac6660aceb86da2f660da923f036637248087 --- /dev/null +++ b/asynio/ioimpl/ioasyn.h @@ -0,0 +1,19 @@ +#ifndef _IO_ASYN_H_ +#define _IO_ASYN_H_ + +#include "ioeventdef.h" + +uvNameSpaceBegin + + +struct io_asyn_t { + uv_async_t asyndata; + io_data io; +}; +int do_async_send(uv_loop_t* eventloop, async_fun_cb func, async_fun_cb freefunc, void* pThis); +int do_async_io_send(uv_loop_t* eventloop, io_asyn_t* p); + +uvNameSpaceEnd + +#endif + diff --git a/asynio/ioimpl/ioconnect.cpp b/asynio/ioimpl/ioconnect.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2782e9dc42a9674bb8621883a212a8f231349fd6 --- /dev/null +++ b/asynio/ioimpl/ioconnect.cpp @@ -0,0 +1,6 @@ +#include "ioconnect.h" + +uvNameSpaceBegin + + +uvNameSpaceEnd diff --git a/asynio/ioimpl/ioconnect.h b/asynio/ioimpl/ioconnect.h new file mode 100644 index 0000000000000000000000000000000000000000..1ff1d1d3ddea8e86cd0ac6eade7f0c8490ee233e --- /dev/null +++ b/asynio/ioimpl/ioconnect.h @@ -0,0 +1,25 @@ +#ifndef _IO_CONNECT_H_ +#define _IO_CONNECT_H_ + +#include "ioreq.h" + +uvNameSpaceBegin + +/* + +class io_connect_t : public io_req_t +{ +public: + io_connect_t(io_asyn_t::ProviderType provider) :io_req_t(provider) { + + } + ~io_connect_t() { + + } +}; + +*/ + +uvNameSpaceEnd + +#endif diff --git a/asynio/ioimpl/ioconnection.cpp b/asynio/ioimpl/ioconnection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b087e49c0a9572ce6be0a84ed8b792956830372 --- /dev/null +++ b/asynio/ioimpl/ioconnection.cpp @@ -0,0 +1,5 @@ +#include "ioconnection.h" + +uvNameSpaceBegin + +uvNameSpaceEnd \ No newline at end of file diff --git a/asynio/ioimpl/ioconnection.h b/asynio/ioimpl/ioconnection.h new file mode 100644 index 0000000000000000000000000000000000000000..e6353236cdd80b3b3d24f19d567b686cc938c303 --- /dev/null +++ b/asynio/ioimpl/ioconnection.h @@ -0,0 +1,41 @@ +#ifndef _IO_CONNECTION_H_ +#define _IO_CONNECTION_H_ + +#include "iostreambase.h" + +uvNameSpaceBegin + +/* + +template +class io_connection_t : public io_stream_t +{ +public: + io_connection_t(io_asyn_t::ProviderType provider):io_stream_t(provider) { + + } + virtual ~io_connection_t() { + + } + CPP_INLINE ConnectType* Handle() { + return &m_handle_; + } + static CPP_INLINE void OnAccept(uv_stream_t* handle, int status) { + + } + static CPP_INLINE void OnConnection(uv_connect_t* req, int status) { + + io_connect_t* wrap_data = static_cast(req->data); + Type* wrap = static_cast(req->handle->data); + + + } +private: + ConnectType m_handle_; +}; +*/ + +uvNameSpaceEnd + +#endif + diff --git a/asynio/ioimpl/ioeventdef.h b/asynio/ioimpl/ioeventdef.h new file mode 100644 index 0000000000000000000000000000000000000000..a61da6bd37c802816e77ebfc9fb3d94e74d72ff4 --- /dev/null +++ b/asynio/ioimpl/ioeventdef.h @@ -0,0 +1,73 @@ +#ifndef _IOEVENTDEF_H_ +#define _IOEVENTDEF_H_ + + + +#include + +#include +#include +using namespace std; + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined (WIN32) || defined(_WIN32) +#define uv_thread_sleep(ms) Sleep(ms);//˯ÃßmsºÁÃë +#elif defined(__linux__) +#define uv_thread_close(t) () +#define uv_thread_sleep(ms) usleep((ms) * 1000) +#else +#error "no supported os" +#endif + + + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +#define container_of(ptr, type, member) \ + ((type *) ((char *) (ptr) - offsetof(type, member))) + + + +#ifdef __cplusplus + +#define uvNameSpaceBegin namespace iouv { +#define uvNameSpaceEnd } +#define uvNameSpace using namespace iouv; + + +#else + +#define uvNameSpaceBegin +#define uvNameSpaceEnd +#define uvNameSpace + + +#endif + +#include "ioallocator.h" +#include "ioeventloop.h" + + +typedef void(*async_fun_cb)(void *pData); + + +struct io_data { + void* pdata; + int uSendId; + int uRecvId; + async_fun_cb func; + async_fun_cb freefunc; +}; + +#endif // _IOEVENTDEF_H_ + diff --git a/asynio/ioimpl/ioeventloop.cpp b/asynio/ioimpl/ioeventloop.cpp new file mode 100644 index 0000000000000000000000000000000000000000..af3de3fbefc95a59a13236a4cdd2932f4cda03c9 --- /dev/null +++ b/asynio/ioimpl/ioeventloop.cpp @@ -0,0 +1,87 @@ +#include "ioeventloop.h" +#include "ioallocator.h" + +uvNameSpaceBegin + + +static io_event_loop* eventloop = NULL; +static uv_mutex_t mutex; +static uv_once_t initonce = UV_ONCE_INIT; + +////////////////////////////////////////////////////////////////////////////////// +io_event_loop* create_ioeventloop() { + + io_event_loop* ioevent = (io_event_loop*)iouv_malloc_func(sizeof(io_event_loop)); + memset(ioevent, 0, sizeof(io_event_loop)); + ioevent->loop = uv_loop_new(); + uv_loop_init(ioevent->loop); + return ioevent; +} +int destory_ioeventloop(io_event_loop* eventloop) { + + if (eventloop != NULL) { + uv_loop_close(eventloop->loop); + uv_loop_delete(eventloop->loop); + iouv_free_func(eventloop); + } + return 1; +} +int run_ioeventloop(io_event_loop* eventloop) { + + return uv_run(eventloop->loop, UV_RUN_DEFAULT); +} +////////////////////////////////////////////////////////////////////////////////// + + +static void free_ioeventloop(io_event_loop* evloop) { + + uv_mutex_lock(&mutex); + iouv_free_func(evloop); + uv_mutex_unlock(&mutex); +} + +static void init_eventloop_once(void) { + uv_mutex_init(&mutex); + uv_mutex_lock(&mutex); + eventloop = create_ioeventloop(); + uv_mutex_unlock(&mutex); + +} +static void uninit_eventloop_once(void) { + + uv_mutex_destroy(&mutex); + free_ioeventloop(eventloop); +} +static io_event_loop* get_ioeventloop() { + + uv_once(&initonce, init_eventloop_once); + + uv_mutex_lock(&mutex); + eventloop->iref++; + uv_mutex_unlock(&mutex); + return eventloop; +} + +io_event_loop* create_instance_ioeventloop() { + + return get_ioeventloop(); +} +io_event_loop* get_instance_ioeventloop() { + + return get_ioeventloop(); +} +int delete_instance_ioeventloop(io_event_loop* eventloop) { + + uv_mutex_lock(&mutex); + if (eventloop->iref-- == 0) + uninit_eventloop_once(); + uv_mutex_unlock(&mutex); + return 1; +} + + + + + + +uvNameSpaceEnd \ No newline at end of file diff --git a/asynio/ioimpl/ioeventloop.h b/asynio/ioimpl/ioeventloop.h new file mode 100644 index 0000000000000000000000000000000000000000..3b16cb7e90590d556fa342911117e414932ac587 --- /dev/null +++ b/asynio/ioimpl/ioeventloop.h @@ -0,0 +1,30 @@ +#ifndef _IO_EVENT_LOOP_H_ +#define _IO_EVENT_LOOP_H_ + +#include "ioeventdef.h" + +uvNameSpaceBegin + + +struct io_event_loop +{ + uv_loop_t* loop; + int binit; + int iref; +}; + +io_event_loop* create_ioeventloop(); +int destory_ioeventloop(io_event_loop* eventloop); +int run_ioeventloop(io_event_loop* eventloop); + +io_event_loop* create_instance_ioeventloop(); +io_event_loop* get_instance_ioeventloop(); +int delete_instance_ioeventloop(io_event_loop* eventloop); + + + + +uvNameSpaceEnd + + +#endif \ No newline at end of file diff --git a/asynio/ioimpl/iofile.cpp b/asynio/ioimpl/iofile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..375f6749662d9a0d18222b9aa43836eb406dcb10 --- /dev/null +++ b/asynio/ioimpl/iofile.cpp @@ -0,0 +1,15 @@ +#include "iofile.h" + +uvNameSpaceBegin + +io_file_t::io_file_t() { + +} +io_file_t::~io_file_t() { + +} +int io_file_t::file_open(const char *filepath, int flags, int mode) { + + return 1; +} +uvNameSpaceEnd diff --git a/asynio/ioimpl/iofile.h b/asynio/ioimpl/iofile.h new file mode 100644 index 0000000000000000000000000000000000000000..1bd65ef675ea54844e75528e2c7e2034fc770f80 --- /dev/null +++ b/asynio/ioimpl/iofile.h @@ -0,0 +1,21 @@ +#ifndef _IOFILE_H_ +#define _IOFILE_H_ + +#include "ioeventdef.h" + +uvNameSpaceBegin + +class io_file_t { + +public: + io_file_t(); + virtual ~io_file_t(); +public: + int file_open(const char *filepath, int flags, int mode); + + +}; + +uvNameSpaceEnd + +#endif \ No newline at end of file diff --git a/asynio/ioimpl/iohandler.h b/asynio/ioimpl/iohandler.h new file mode 100644 index 0000000000000000000000000000000000000000..86f6eb9395c669edaf879c267f883a10d6583131 --- /dev/null +++ b/asynio/ioimpl/iohandler.h @@ -0,0 +1,53 @@ +#ifndef _IOHANDLER_H_ +#define _IOHANDLER_H_ + +#include "ioeventdef.h" +#include "ioasyn.h" + +uvNameSpaceBegin + +/* + + +class io_handler_t : public io_asyn_t { +public: + + static inline bool IsAlive(const io_handler_t* wrap) { + return wrap != nullptr && wrap->state_ != kClosed; + } + + static inline bool HasRef(const io_handler_t* wrap) { + return IsAlive(wrap) && uv_has_ref(wrap->GetHandle()); + } + + inline uv_handle_t* GetHandle() const { + return handle_; + } + +protected: + io_handler_t(uv_handle_t* handle, io_asyn_t::ProviderType provider ): handle_(handle), io_asyn_t(provider) { + + } + virtual ~io_handler_t() { + + } + +private: + + static void OnClose(uv_handle_t* handle); + + enum { + kInitialized, + kClosing, + kClosingWithCallback, + kClosed + } state_; + + uv_handle_t* const handle_; +}; + +*/ + +uvNameSpaceEnd + +#endif diff --git a/asynio/ioimpl/iolock.h b/asynio/ioimpl/iolock.h new file mode 100644 index 0000000000000000000000000000000000000000..5661fb846a23d3858232b4f2e65925429f4dbdf6 --- /dev/null +++ b/asynio/ioimpl/iolock.h @@ -0,0 +1,199 @@ +#ifndef _IOLOCKS_H_ +#define _IOLOCKS_H_ + +#include "ioeventdef.h" + +uvNameSpaceBegin + +class CUVMutex +{ +public: + CUVMutex() + { + uv_mutex_init(&mut_); + } + ~CUVMutex(void) + { + uv_mutex_destroy(&mut_); + } + void Lock() + { + uv_mutex_lock(&mut_); + } + void UnLock() + { + uv_mutex_unlock(&mut_); + } + bool TryLock() + { + return uv_mutex_trylock(&mut_) == 0; + } +private: + uv_mutex_t mut_; + friend class CUVCond; + friend class CUVAutoLock; +private: + CUVMutex(const CUVMutex&); + CUVMutex& operator =(const CUVMutex&); +}; + +class CUVAutoLock +{ +public: + CUVAutoLock(CUVMutex* mut) : mut_(&mut->mut_) + { + uv_mutex_lock(mut_); + } + ~CUVAutoLock(void) + { + uv_mutex_unlock(mut_); + } +private: + uv_mutex_t * mut_; +private: + CUVAutoLock(const CUVAutoLock&); + CUVAutoLock& operator =(const CUVAutoLock&); +}; + +class CUVCond +{ +public: + CUVCond() + { + uv_cond_init(&cond_); + } + ~CUVCond(void) + { + uv_cond_destroy(&cond_); + } + void Signal() + { + uv_cond_signal(&cond_); + } + void BroadCast() + { + uv_cond_broadcast(&cond_); + } + void Wait(CUVMutex* mutex) + { + uv_cond_wait(&cond_, &mutex->mut_); + } + void Wait(uv_mutex_t* mutex) + { + uv_cond_wait(&cond_, mutex); + } + int Wait(CUVMutex* mutex, uint64_t timeout) + { + return uv_cond_timedwait(&cond_, &mutex->mut_, timeout); + } + int Wait(uv_mutex_t* mutex, uint64_t timeout) + { + return uv_cond_timedwait(&cond_, mutex, timeout); + } +private: + uv_cond_t cond_; +private: + CUVCond(const CUVCond&); + CUVCond& operator =(const CUVCond&); +}; + +class CUVSem +{ +public: + CUVSem() + { + uv_sem_init(&sem_, 0); + } + virtual ~CUVSem(void) + { + uv_sem_destroy(&sem_); + } + void Post() + { + uv_sem_post(&sem_); + } + void Wait() + { + uv_sem_wait(&sem_); + } + bool TryWait() + { + return uv_sem_trywait(&sem_) == 0; + } +private: + uv_sem_t sem_; +private: + CUVSem(const CUVSem&); + CUVSem& operator =(const CUVSem&); +}; + +class CUVRWLock +{ +public: + CUVRWLock() + { + uv_rwlock_init(&rwlock_); + } + ~CUVRWLock(void) + { + uv_rwlock_destroy(&rwlock_); + } + void ReadLock() + { + uv_rwlock_rdlock(&rwlock_); + } + void ReadUnLock() + { + uv_rwlock_rdunlock(&rwlock_); + } + bool ReadTryLock() + { + return uv_rwlock_tryrdlock(&rwlock_) == 0; + } + void WriteLock() + { + uv_rwlock_wrlock(&rwlock_); + } + void WriteUnLock() + { + uv_rwlock_wrunlock(&rwlock_); + } + bool WriteTryLock() + { + return uv_rwlock_trywrlock(&rwlock_) == 0; + } +private: + uv_rwlock_t rwlock_; +private: + CUVRWLock(const CUVRWLock&); + CUVRWLock& operator =(const CUVRWLock&); +}; + +class CUVBarrier +{ +public: + CUVBarrier(int count) + { + uv_barrier_init(&barrier_, count); + } + ~CUVBarrier(void) + { + uv_barrier_destroy(&barrier_); + } + void Wait() + { + uv_barrier_wait(&barrier_); + } +private: + uv_barrier_t barrier_; +private: + CUVBarrier(const CUVBarrier&); + CUVBarrier& operator =(const CUVBarrier&); +}; + + + + +uvNameSpaceEnd + +#endif \ No newline at end of file diff --git a/asynio/ioimpl/iooperation.cpp b/asynio/ioimpl/iooperation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6130cd74edd599845fe5aa86cd82b89d4b28ab48 --- /dev/null +++ b/asynio/ioimpl/iooperation.cpp @@ -0,0 +1,7 @@ +#include "iooperation.h" + + +uvNameSpaceBegin + + +uvNameSpaceEnd diff --git a/asynio/ioimpl/iooperation.h b/asynio/ioimpl/iooperation.h new file mode 100644 index 0000000000000000000000000000000000000000..45ce0fbc61f5cd189f1885f6a025cec38a7343c1 --- /dev/null +++ b/asynio/ioimpl/iooperation.h @@ -0,0 +1,21 @@ +#ifndef _IOOPERATION_H_ +#define _IOOPERATION_H_ + +#include "ioeventdef.h" + +uvNameSpaceBegin + +typedef void(*operation_fun_cb)(void *pData); + +struct io_operation_t { + io_event_loop* eventloop; + uv_work_t* worker; + uv_async_t* async; + operation_fun_cb cb; + void* data; + +}; + +uvNameSpaceEnd + +#endif \ No newline at end of file diff --git a/asynio/ioimpl/ioqueue.h b/asynio/ioimpl/ioqueue.h new file mode 100644 index 0000000000000000000000000000000000000000..194bc2d5f095287f3f53c2d2de26aa50bb715f86 --- /dev/null +++ b/asynio/ioimpl/ioqueue.h @@ -0,0 +1,104 @@ +#ifndef _IOQUEUE_H_ +#define _IOQUEUE_H_ + +#include "ioeventdef.h" +#include "iolock.h" + +#include + +uvNameSpaceBegin + + +template +class TaskQueue { +public: + TaskQueue() { + m_TaskSize = 0; + m_Stopped = false; + } + ~TaskQueue() { + + } + int Size() { + return task_queue_.size(); + } + bool IsEmpty() { + return task_queue_.empty(); + } + void Push(T task) { + + CUVAutoLock lock(&m_Mutex); + m_TaskSize++; + m_TaskQueue.push(task); + m_CondTasksAvailable.Signal(); + } + T Pop() { + + CUVAutoLock lock(&m_Mutex); + + T result = nullptr; + if (!m_TaskQueue.empty()) { + result = m_TaskQueue.front(); + m_TaskQueue.pop(); + } + return result; + } + T BlockingPop() { + + CUVAutoLock lock(&m_Mutex); + while (m_TaskQueue.empty() && !m_Stopped) { + m_CondTasksAvailable.Wait(&m_Mutex); + } + + if (m_Stopped) { + return nullptr; + } + T result = nullptr; + + result = m_TaskQueue.front(); + m_TaskQueue.pop(); + return result; + } + + void NotifyOfCompletion() { + + CUVAutoLock lock(&m_Mutex); + if (--m_TaskSize == 0) { + m_CondTasksDrained.BroadCast(); + } + + } + void BlockingDrain() { + + CUVAutoLock lock(&m_Mutex); + while (m_TaskSize > 0) { + m_CondTasksDrained.Wait(lock); + } + } + void Stop() { + + CUVAutoLock lock(&m_Mutex); + m_Stopped = true; + m_CondTasksAvailable.BroadCast(); + } + +private: + std::queue m_TaskQueue; + CUVMutex m_Mutex; + CUVCond m_CondTasksAvailable; + CUVCond m_CondTasksDrained; + int m_TaskSize; + bool m_Stopped; + +}; + + + + + + + +uvNameSpaceEnd + +#endif + diff --git a/asynio/ioimpl/ioreq.cpp b/asynio/ioimpl/ioreq.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39e696323a0583140c032d0e7aedfdaae0ce0769 --- /dev/null +++ b/asynio/ioimpl/ioreq.cpp @@ -0,0 +1,2 @@ +#include "ioreq.h" + diff --git a/asynio/ioimpl/ioreq.h b/asynio/ioimpl/ioreq.h new file mode 100644 index 0000000000000000000000000000000000000000..7d39320e6dfcf11d68c111f4259640f14eafc375 --- /dev/null +++ b/asynio/ioimpl/ioreq.h @@ -0,0 +1,33 @@ +#ifndef _IO_REQ_H_ +#define _IO_REQ_H_ + +#include "ioasyn.h" + +uvNameSpaceBegin + +/* +template +class io_req_t : public io_asyn_t +{ +public: + CPP_INLINE io_req_t(io_asyn_t::ProviderType provider):io_asyn_t(provider) { + + } + CPP_INLINE ~io_req_t() { + + } + ConnectT* req() { return &m_req; } + + void Dispatched() { + m_req.data = this; + } + +public: + ConnectT m_req; + +}; +*/ + +uvNameSpaceEnd + +#endif diff --git a/asynio/ioimpl/ioresp.cpp b/asynio/ioimpl/ioresp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e3e3d359b342acad1bfd60481d55ad1620a7e1ce --- /dev/null +++ b/asynio/ioimpl/ioresp.cpp @@ -0,0 +1 @@ +#include "ioresp.h" diff --git a/asynio/ioimpl/ioresp.h b/asynio/ioimpl/ioresp.h new file mode 100644 index 0000000000000000000000000000000000000000..c851950871c76702205cd930d18cdc063e78fff2 --- /dev/null +++ b/asynio/ioimpl/ioresp.h @@ -0,0 +1,29 @@ +#ifndef _IO_RESP_H_ +#define _IO_RESP_H_ + +#include "ioasyn.h" + +uvNameSpaceBegin + +/* + +template +class io_resp_t +{ +public: + CPP_INLINE io_resp_t() { + + } + CPP_INLINE ~io_resp_t() { + + } + ConnectT* req() { return &m_req; } +public: + ConnectT m_req; +}; +*/ + +uvNameSpaceEnd + +#endif + diff --git a/asynio/ioimpl/iostreambase.cpp b/asynio/ioimpl/iostreambase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..da029df985784af0adedc8105f3cfa8983b31707 --- /dev/null +++ b/asynio/ioimpl/iostreambase.cpp @@ -0,0 +1,158 @@ +#include "iostreambase.h" +#include "ioeventloop.h" + +uvNameSpaceBegin + +/* + +io_stream_t::io_stream_t(io_asyn_t::ProviderType provider) : + io_handler_t(reinterpret_cast(m_stream), provider) { + +} +io_stream_t::~io_stream_t() { + +} +int io_stream_t::ReadStart() { + + return uv_read_start(stream(), OnAlloc, OnRead); +} +int io_stream_t::ReadStop() { + + return uv_read_stop(stream()); +} + +uv_stream_t* io_stream_t::stream() const { + return m_stream; +} + +void* io_stream_t::Cast() { + return reinterpret_cast(this); +} +bool io_stream_t::IsClosing() { + return uv_is_closing(reinterpret_cast(stream())); +} +bool io_stream_t::IsAlive() { + return io_handler_t::IsAlive(this); +} +bool io_stream_t::IsIPCPipe() const { + return stream()->type == UV_NAMED_PIPE; +} +bool io_stream_t::is_named_pipe_ipc() const { + return IsIPCPipe() && reinterpret_cast(stream())->ipc != 0; +} +bool io_stream_t::IsTcp() const { + return stream()->type == UV_TCP; +} +bool io_stream_t::IsUdp() const { + return stream()->type == UV_UDP; +} + +int io_stream_t::DoShutdown(io_shutdown_t* req_wrap) { + + int err; + req_wrap->Dispatched(); + err = uv_shutdown(req_wrap->req(), stream(), DoShutdownDone); + return err; +} +int io_stream_t::DoTryWrite(uv_buf_t** bufs, size_t* count) { + + int err; + size_t written; + uv_buf_t* vbufs = *bufs; + size_t vcount = *count; + + err = uv_try_write(stream(), vbufs, vcount); + if (err == UV_ENOSYS || err == UV_EAGAIN) + return 0; + if (err < 0) + return err; + written = err; + for (; vcount > 0; vbufs++, vcount--) { + // Slice + if (vbufs[0].len > written) { + vbufs[0].base += written; + vbufs[0].len -= written; + written = 0; + break; + } + else { + written -= vbufs[0].len; + } + } + + *bufs = vbufs; + *count = vcount; + return 0; +} +int io_stream_t::DoWrite(io_write_t* w, uv_buf_t* bufs, size_t count, uv_stream_t* send_handle) { + + int r; + if (send_handle == nullptr) { + r = uv_write(w->req(), stream(), bufs, count, DoWriteDone); + } + else { + r = uv_write2(w->req(), stream(), bufs, count, send_handle, DoWriteDone); + } + + if (!r) { + size_t bytes = 0; + for (size_t i = 0; i < count; i++) + bytes += bufs[i].len; + if (stream()->type == UV_TCP) { + + } + else if (stream()->type == UV_NAMED_PIPE) { + + } + } + return r; + +} + +void io_stream_t::OnAlloc(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf) { + + + +} + +void io_stream_t::OnRead(uv_stream_t* handle, + ssize_t nread, + const uv_buf_t* buf) { + + io_stream_t* wrap = static_cast(handle->data); + + uv_handle_type type = UV_UNKNOWN_HANDLE; + + if (wrap->IsIPCPipe() && + uv_pipe_pending_count(reinterpret_cast(handle)) > 0) { + type = uv_pipe_pending_type(reinterpret_cast(handle)); + } + + static_cast(wrap)->OnRead(nread, buf, type); + +} +void io_stream_t::DoWriteDone(uv_write_t* req, int status) { + +} +void io_stream_t::DoShutdownDone(uv_shutdown_t* req, int status) { + +} + +void io_stream_t::OnAfterWriteImpl(io_write_t* w, void* ctx) { + +} +void io_stream_t::OnAllocImpl(size_t size, uv_buf_t* buf, void* ctx) { + +} +void io_stream_t::OnReadImpl(ssize_t nread, + const uv_buf_t* buf, + uv_handle_type pending, + void* ctx) { + +} + +*/ + +uvNameSpaceEnd \ No newline at end of file diff --git a/asynio/ioimpl/iostreambase.h b/asynio/ioimpl/iostreambase.h new file mode 100644 index 0000000000000000000000000000000000000000..21c8db2b900c69d80ec4e7e6395c300182f86c33 --- /dev/null +++ b/asynio/ioimpl/iostreambase.h @@ -0,0 +1,221 @@ +#ifndef _IOSTREAMBASE_H_ +#define _IOSTREAMBASE_H_ + +#include "ioeventdef.h" +#include "iohandler.h" +#include "ioreq.h" + +uvNameSpaceBegin + + +/* + + +template +struct Callback { + Callback() : fn(nullptr), ctx(nullptr) { + + } + Callback(T fn, void* ctx) : fn(fn), ctx(ctx) { + + } + inline bool is_empty() { + return fn == nullptr; + } + inline void clear() { + fn = nullptr; + ctx = nullptr; + } + T fn; + void* ctx; +}; + + + +class io_streambase; + +template +class io_stream_req { + +public: + typedef void(*DoneCb)(Req* req, int status); +protected: + explicit io_stream_req(DoneCb cb, io_streambase* base) : cb_(cb), streambase(base) { + + } + inline void Done(int status, const char* error_str = nullptr) { + + cb_(req, status); + } +public: + inline io_streambase* Get() const { + return streambase; + } +protected: + io_streambase * const streambase; + DoneCb cb_; +}; + + +class io_shutdown_t : public io_req_t, public io_stream_req { +protected: + io_shutdown_t(io_streambase* base,DoneCb cb): + io_stream_req(cb, base), + io_req_t(io_asyn_t::PROVIDER_SHUTDOWNWRAP) { + + } + ~io_shutdown_t() { + + } +}; + +class io_write_t : public io_req_t, public io_stream_req { + +protected: + io_write_t(io_streambase* base, DoneCb cb): + io_stream_req(cb, base), + io_req_t(io_asyn_t::PROVIDER_WRITEWRAP) { + + } + ~io_write_t() { + + } +}; + +class io_streamresource_t { + +public: + + typedef void(*AfterWriteCb)(io_write_t* w, void* ctx); + typedef void(*AllocCb)(size_t size, uv_buf_t* buf, void* ctx); + typedef void(*ReadCb)(ssize_t nread, + const uv_buf_t* buf, + uv_handle_type pending, + void* ctx); + typedef void(*DestructCb)(void* ctx); + + io_streamresource_t() : bytes_read_(0) { + + } + virtual ~io_streamresource_t() { + if (!destruct_cb_.is_empty()) + destruct_cb_.fn(destruct_cb_.ctx); + } + + virtual int DoShutdown(io_shutdown_t* req_wrap) = 0; + virtual int DoTryWrite(uv_buf_t** bufs, size_t* count) = 0; + virtual int DoWrite(io_write_t* w, + uv_buf_t* bufs, + size_t count, + uv_stream_t* send_handle) = 0; + + // Events + inline void OnAfterWrite(io_write_t* w) { + if (!after_write_cb_.is_empty()) + after_write_cb_.fn(w, after_write_cb_.ctx); + } + + inline void OnAlloc(size_t size, uv_buf_t* buf) { + if (!alloc_cb_.is_empty()) + alloc_cb_.fn(size, buf, alloc_cb_.ctx); + } + + inline void OnRead(ssize_t nread, + const uv_buf_t* buf, + uv_handle_type pending = UV_UNKNOWN_HANDLE) { + if (nread > 0) + bytes_read_ += static_cast(nread); + if (!read_cb_.is_empty()) + read_cb_.fn(nread, buf, pending, read_cb_.ctx); + } + + inline void set_after_write_cb(Callback c) { + after_write_cb_ = c; + } + + inline void set_alloc_cb(Callback c) { alloc_cb_ = c; } + inline void set_read_cb(Callback c) { read_cb_ = c; } + inline void set_destruct_cb(Callback c) { destruct_cb_ = c; } + + inline Callback after_write_cb() { return after_write_cb_; } + inline Callback alloc_cb() { return alloc_cb_; } + inline Callback read_cb() { return read_cb_; } + inline Callback destruct_cb() { return destruct_cb_; } + +private: + Callback after_write_cb_; + Callback alloc_cb_; + Callback read_cb_; + Callback destruct_cb_; + uint64_t bytes_read_; +}; + + +class io_streambase : public io_streamresource_t { + +protected: + io_streambase() { + + } + + virtual ~io_streambase() { + + } +public: + virtual void* Cast() = 0; + virtual bool IsClosing() = 0; + virtual bool IsIPCPipe() const = 0; + virtual bool is_named_pipe_ipc() const = 0; + virtual bool IsTcp() const = 0; + virtual bool IsUdp() const = 0; + +}; + +class io_stream_t : public io_handler_t , public io_streambase { + +public: + io_stream_t(io_asyn_t::ProviderType provider); + virtual ~io_stream_t(); + int ReadStart(); + int ReadStop(); + uv_stream_t* stream() const; + void* Cast(); + bool IsClosing(); + bool IsAlive(); + bool IsIPCPipe() const; + bool is_named_pipe_ipc() const; + bool IsTcp() const; + bool IsUdp() const; + + int DoShutdown(io_shutdown_t* req_wrap); + int DoTryWrite(uv_buf_t** bufs, size_t* count); + int DoWrite(io_write_t* w, uv_buf_t* bufs, size_t count, uv_stream_t* send_handle); + + + static void OnAlloc(uv_handle_t* handle, + size_t suggested_size, + uv_buf_t* buf); + static void OnRead(uv_stream_t* handle, + ssize_t nread, + const uv_buf_t* buf); + + static void DoWriteDone(uv_write_t* req, int status); + static void DoShutdownDone(uv_shutdown_t* req, int status); + + static void OnAfterWriteImpl(io_write_t* w, void* ctx); + static void OnAllocImpl(size_t size, uv_buf_t* buf, void* ctx); + static void OnReadImpl(ssize_t nread, + const uv_buf_t* buf, + uv_handle_type pending, + void* ctx); + + +private: + uv_stream_t* m_stream; +}; + +*/ + +uvNameSpaceEnd + +#endif diff --git a/asynio/ioimpl/iotcpbase.cpp b/asynio/ioimpl/iotcpbase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5f6971a1db9cd9834ced4d0ad4e70dcac7501b0f --- /dev/null +++ b/asynio/ioimpl/iotcpbase.cpp @@ -0,0 +1,105 @@ +#include "iotcpbase.h" +#include "ioeventloop.h" +#include "iooperation.h" + +uvNameSpaceBegin + +void OnAccept(uv_stream_t* server, int status) { + +} +void OnConnection(uv_connect_t* req, int status) { + + //DWORD dwThreadid = GetCurrentThreadId(); + //char log[128] = { 0x00 }; + //sprintf(log, "Tcp thread id :%u\n", dwThreadid); + //OutputDebugStringA(log); + + //io_operation_t* p = static_cast(req->data); + //p->m_hMsgfunc(OP_TCPSOCKET_CONNECT); +} + +int io_tcp_init(io_tcp_i* pTcp) { + + pTcp->tcp = (uv_tcp_t*)iouv_malloc_func(sizeof(uv_tcp_t)); + uv_tcp_init(get_instance_ioeventloop()->loop, pTcp->tcp); + pTcp->connect = (uv_connect_t*)iouv_malloc_func(sizeof(uv_connect_t)); + + return 1; +} + +int io_tcp_uninit(io_tcp_i* pTcp) { + + if (pTcp != NULL) { + iouv_free_func(pTcp->tcp); + iouv_free_func(pTcp->connect); + iouv_free_func(pTcp); + } + return 1; +} +int io_tcp_open(io_tcp_i *pTcp, os_sock_t sock) { + + int r = 0; + uv_tcp_open(pTcp->tcp, sock); + + return r == 0 ? 0 : 1; +} +int io_tcp_listen(io_tcp_i *pTcp) { + + int err = uv_listen(reinterpret_cast(pTcp->tcp),10,OnAccept); + + return 1; +} +int io_tcp_connect(io_tcp_i *pTcp, const char* ipaddress,int iport) { + + sockaddr_in addr; + int err = uv_ip4_addr(ipaddress, iport, &addr); + if (err == 0) { + + pTcp->connect->data = pTcp->data; + err = uv_tcp_connect(pTcp->connect, + pTcp->tcp, + reinterpret_cast(&addr), + OnConnection); + + } + return 1; +} +int io_tcp_connect6(io_tcp_i *pTcp, const char* ipaddress, int iport) { + + sockaddr_in6 addr; + int err = uv_ip6_addr(ipaddress, iport, &addr); + + if (err == 0) { + + pTcp->connect->data = pTcp->data; + err = uv_tcp_connect(pTcp->connect, + pTcp->tcp, + reinterpret_cast(&addr), + OnConnection); + } + return 1; +} +int io_tcp_bind(io_tcp_i *pTcp, const char* ipaddress, int iport) { + + sockaddr_in addr; + int err = uv_ip4_addr(ipaddress, iport, &addr); + if (err == 0) { + err = uv_tcp_bind(pTcp->tcp, + reinterpret_cast(&addr), + 0); + } + return 1; +} +int io_tcp_bind6(io_tcp_i *pTcp, const char* ipaddress, int iport) { + + sockaddr_in6 addr; + int err = uv_ip6_addr(ipaddress, iport, &addr); + if (err == 0) { + err = uv_tcp_bind(pTcp->tcp, + reinterpret_cast(&addr), + 0); + } + return 1; +} + +uvNameSpaceEnd diff --git a/asynio/ioimpl/iotcpbase.h b/asynio/ioimpl/iotcpbase.h new file mode 100644 index 0000000000000000000000000000000000000000..85ceb6b18328a3da5fb73e7214f0cb1e33bace62 --- /dev/null +++ b/asynio/ioimpl/iotcpbase.h @@ -0,0 +1,26 @@ +#ifndef _IOTCPBASE_H_ +#define _IOTCPBASE_H_ + +#include "ioconnection.h" +#include "ioconnect.h" + +uvNameSpaceBegin + +struct io_tcp_i { + uv_tcp_t* tcp; + uv_connect_t* connect; + void* data; +}; + +int io_tcp_init(io_tcp_i* pTcp); +int io_tcp_uninit(io_tcp_i* pTcp); +int io_tcp_open(io_tcp_i *pTcp, os_sock_t sock); +int io_tcp_listen(io_tcp_i *pTcp); +int io_tcp_connect(io_tcp_i *pTcp, const char* ipaddress, int iport); +int io_tcp_connect6(io_tcp_i *pTcp, const char* ipaddress, int iport); +int io_tcp_bind(io_tcp_i *pTcp, const char* ipaddress, int iport); +int io_tcp_bind6(io_tcp_i *pTcp, const char* ipaddress, int iport); + +uvNameSpaceEnd + +#endif diff --git a/asynio/ioimpl/iothread.cpp b/asynio/ioimpl/iothread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6360da3b9bb43e200ebb08b18eca3191302f71e2 --- /dev/null +++ b/asynio/ioimpl/iothread.cpp @@ -0,0 +1,59 @@ +#include "iothread.h" + +uvNameSpaceBegin + + + + +static void do_work(void* arg) { + + io_thread_t* p = (io_thread_t*)(arg); + p->startfunction(p->data); + run_ioeventloop(p->eventloop); + p->stopfunction(p->data); +} +static void thread_close_cb(uv_handle_t* handle) +{ + +} +static void AsyncTasks(uv_async_t* handle) { + + //uv_close((uv_handle_t*)handle, thread_close_cb); +} + +static void wait_thread_idle(uv_idle_t* handle) { + +} +static void initasync(io_thread_t* pThis) { + + pThis->async.data = (void*)(pThis); + uv_async_init(pThis->eventloop->loop, &pThis->async, AsyncTasks); + uv_async_send(&pThis->async); + uv_ref((uv_handle_t*)(&pThis->async)); +} +int thread_init(io_thread_t* pThis,void* pdata, async_fun_cb startcb, async_fun_cb stopcb) { + + pThis->eventloop = create_ioeventloop(); + pThis->eventloop = create_ioeventloop(); + pThis->startfunction = startcb; + pThis->stopfunction = stopcb; + pThis->data = pdata; + + initasync(pThis); + + return 1; +} +int thread_start(io_thread_t* pThis) { + + uv_thread_create(&pThis->thread, do_work, pThis); + return 1; +} +int thread_stop(io_thread_t* pThis) { + + uv_thread_join(&pThis->thread); + uv_close((uv_handle_t*)(&pThis->async), thread_close_cb); + destory_ioeventloop(pThis->eventloop); + + return 1; +} +uvNameSpaceEnd diff --git a/asynio/ioimpl/iothread.h b/asynio/ioimpl/iothread.h new file mode 100644 index 0000000000000000000000000000000000000000..d727b6500ed6410a4d4e63f1e1d238e26331bb58 --- /dev/null +++ b/asynio/ioimpl/iothread.h @@ -0,0 +1,28 @@ +#ifndef _IOTHREAD_H_ +#define _IOTHREAD_H_ + +#include "ioeventdef.h" + + +uvNameSpaceBegin + + +struct io_thread_t { + io_event_loop* eventloop; + uv_thread_t thread; + uv_idle_t idler; + uv_async_t async; + async_fun_cb startfunction; + async_fun_cb stopfunction; + void* data; + int status; +}; + +int thread_init(io_thread_t* pThis, void* pdata, async_fun_cb startcb, async_fun_cb stopcb); +int thread_start(io_thread_t* pThis); +int thread_stop(io_thread_t* pThis); + + +uvNameSpaceEnd + +#endif \ No newline at end of file diff --git a/asynio/ioimpl/iothreadpool.cpp b/asynio/ioimpl/iothreadpool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0b098429d6ea8f0e1838056c5d20dda19c1c02f7 --- /dev/null +++ b/asynio/ioimpl/iothreadpool.cpp @@ -0,0 +1,243 @@ +#include "iothreadpool.h" + + +uvNameSpaceBegin + + +static io_thread_pool* threadpool; +static uv_once_t once = UV_ONCE_INIT; + +/* + +static uv_cond_t cond; +static uv_mutex_t mutex; +static unsigned long uindex = 0; +static long indexlock; +*/ + +struct WokerCb { + io_data io; + _QUEUE node; +}; + + +static void close_cb(uv_handle_t* handle) +{ + +} +static void WokerTPFunction(uv_work_t* req) { + + WokerCb* cb = (WokerCb*)(req->data); + if (cb != NULL) { + + do_async_send(req->loop, cb->io.func, cb->io.freefunc,cb->io.pdata); + } + +} +static void WokerTPFunctionDone(uv_work_t* req, int status) { + + if (req != NULL) { + //uv_close((uv_handle_t*)req, close_cb); + if (req->data) { + iouv_free_func(req->data); + req->data = NULL; + } + iouv_free_func(req); + req = NULL; + + } +} +static void setthreadpools(int thread_num) { + + char settingthreadpool[128] = { 0x00 }; + sprintf(settingthreadpool, "UV_THREADPOOL_SIZE=%d", thread_num); + putenv(settingthreadpool); +} + +static void AsyncTasks(uv_async_t* handle) { + + io_thread_pool* p = (io_thread_pool*)(handle->data); + + if (p->startfunction != NULL) + p->startfunction(p->pdata); + + uv_close((uv_handle_t*)handle, close_cb); + + + +} +static void wait_idle(uv_idle_t* handle) { + +} +static void wait_prepare(uv_prepare_t* handle) { + +} +static void wait_check(uv_check_t* handle) { + +} +static void initasync(io_thread_pool* pool) { + + + + + + /* + + threadpool.prepare.data = static_cast(&threadpool); + uv_prepare_init(threadpool.eventloop->loop, &threadpool.prepare); + uv_prepare_start(&threadpool.prepare, wait_prepare); + + threadpool.check.data = static_cast(&threadpool); + uv_check_init(threadpool.eventloop->loop, &threadpool.check); + uv_check_start(&threadpool.check, wait_check); + */ + + pool->idler.data = (void*)(pool); + uv_idle_init(pool->eventloop->loop, &pool->idler); + uv_idle_start(&pool->idler, wait_idle); + + pool->async_tasks.data = (void*)(pool); + uv_async_init(pool->eventloop->loop, &pool->async_tasks, AsyncTasks); + uv_async_send(&pool->async_tasks); + + //uv_unref(reinterpret_cast(&threadpool.async_tasks)); + +} + +static void thread_startcb_func(void* pdata) { + + io_thread_pool* p = (io_thread_pool*)(pdata); + + uv_sem_post(&p->threadsem); + + +} +static void thread_stopcb_func(void* pdata) { + +} +static void start_threads(io_thread_pool* pool) { + + pool->threads = (io_thread_t*)iouv_malloc_func(pool->threadcount * sizeof(io_thread_t)); + + for (unsigned long iloop = 0; iloop < pool->threadcount; iloop++) { + + thread_init(pool->threads + iloop, pool, thread_startcb_func, thread_stopcb_func); + thread_start(pool->threads + iloop); + } + + for (unsigned long i = 0; i < pool->threadcount; i++) + uv_sem_wait(&pool->threadsem); +} + +static void stop_threads(io_thread_pool* pool) { + + + for (unsigned long iloop = 0; iloop < pool->threadcount; iloop++) { + + thread_stop(pool->threads + iloop); + } +} +static void init_once_threadpool() { + + +} +int init_threadpool(io_thread_pool* pThreadPool, unsigned long threads, unsigned long queuethreads, void* pData) { + + + + + pThreadPool->threadcount = threads; + pThreadPool->queuethreadcount = queuethreads; + pThreadPool->binit = true; + pThreadPool->workerproc = NULL; + pThreadPool->startfunction = NULL; + pThreadPool->stopfunction = NULL; + pThreadPool->pdata = pData; + pThreadPool->eventloop = get_instance_ioeventloop(); + pThreadPool->index = 0; + setthreadpools(threads); + + if (uv_cond_init(&pThreadPool->cond)) + abort(); + + if (uv_mutex_init(&pThreadPool->mutex)) + abort(); + + if (uv_sem_init(&pThreadPool->threadsem, 0)) + abort(); + + initasync(pThreadPool); + start_threads(pThreadPool); + + return 1; + +} +int run_threadpool(io_thread_pool* pThreadPool,async_fun_cb Startfn, async_fun_cb Stopfn) { + + if(Startfn != NULL) + pThreadPool->startfunction = Startfn; + if (Stopfn != NULL) + pThreadPool->stopfunction = Stopfn; + + return run_ioeventloop(pThreadPool->eventloop); +} +int stop_threadpool(io_thread_pool* pThreadPool) { + + destory_ioeventloop(pThreadPool->eventloop); + stop_threads(pThreadPool); + uv_close((uv_handle_t*)&pThreadPool->async_tasks, close_cb); + + uv_sem_destroy(&pThreadPool->threadsem); + + /* + uv_idle_stop(&threadpool.idler); + uv_check_stop(&threadpool.check); + uv_prepare_stop(&threadpool.prepare); + */ + + return 1; +} +int setoncethreadspool(io_thread_pool* pThreadPool) { + + if (threadpool == NULL) { + threadpool = pThreadPool; + } + else { + return 0; + } + uv_once(&once, init_once_threadpool); + return 1; +} +int post_io_threadpool(io_thread_pool* pThreadPool,void* pThis, async_fun_cb func) { + + + io_thread_pool *pTPool = pThreadPool == NULL ? threadpool : pThreadPool; + if (!pTPool->eventloop->loop) + return 0; + + + uv_work_t* iopt = NULL; + iopt = (uv_work_t*)iouv_malloc_func(sizeof(uv_work_t)); + + WokerCb* cb = NULL; + cb = (WokerCb*)iouv_malloc_func(sizeof(WokerCb)); + + if (pThis == NULL || func == NULL || iopt == NULL || cb == NULL) + return 0; + cb->io.func = func; + cb->io.pdata = pThis; + iopt->data = cb; + + + + + unsigned long uloop = pTPool->index; + io_thread_t* p = pTPool->threads + (uloop % pTPool->threadcount); + pTPool->index++; + uv_mutex_lock(&pTPool->mutex); + uv_queue_work(p->eventloop->loop, iopt, WokerTPFunction, WokerTPFunctionDone); + uv_mutex_unlock(&pTPool->mutex); + + return 1; +} +uvNameSpaceEnd \ No newline at end of file diff --git a/asynio/ioimpl/iothreadpool.h b/asynio/ioimpl/iothreadpool.h new file mode 100644 index 0000000000000000000000000000000000000000..d25738794f6063f3df13d8929a6141b029ce0813 --- /dev/null +++ b/asynio/ioimpl/iothreadpool.h @@ -0,0 +1,43 @@ +#ifndef _IOTHREADPOOL_H_ +#define _IOTHREADPOOL_H_ + + +#include "ioeventdef.h" +#include "iothread.h" +#include "ioasyn.h" + +uvNameSpaceBegin + + +struct io_thread_pool { + io_event_loop* eventloop; + uv_async_t async_tasks; + uv_idle_t idler; + uv_prepare_t prepare; + uv_check_t check; + uv_req_t req; + async_fun_cb startfunction; + async_fun_cb stopfunction; + async_fun_cb workerproc; + void* pdata; + unsigned long threadcount; + unsigned long queuethreadcount; + int binit; + io_event_loop* thredseventloop; + io_thread_t* threads; + uv_cond_t cond; + uv_mutex_t mutex; + unsigned long index; + uv_sem_t threadsem; + +}; + +int init_threadpool(io_thread_pool* pThreadPool,unsigned long threads, unsigned long queuethreads, void* pData); +int run_threadpool(io_thread_pool* pThreadPool,async_fun_cb Startfn, async_fun_cb Stopfn); +int stop_threadpool(io_thread_pool* pThreadPool); +int post_io_threadpool(io_thread_pool* pThreadPool,void* pThis, async_fun_cb proc); +int setoncethreadspool(io_thread_pool* pThreadPool); +uvNameSpaceEnd + +#endif + diff --git a/asynio/ioimpl/iowatcher.cpp b/asynio/ioimpl/iowatcher.cpp new file mode 100644 index 0000000000000000000000000000000000000000..356294ef4fdb638c0d2d730494040ec81815402b --- /dev/null +++ b/asynio/ioimpl/iowatcher.cpp @@ -0,0 +1,8 @@ +#include "iowatcher.h" + + +uvNameSpaceBegin + +uvNameSpaceEnd + + diff --git a/asynio/ioimpl/iowatcher.h b/asynio/ioimpl/iowatcher.h new file mode 100644 index 0000000000000000000000000000000000000000..2e31a98dd3e6d48507c46f383457eb407dff9e22 --- /dev/null +++ b/asynio/ioimpl/iowatcher.h @@ -0,0 +1,12 @@ +#ifndef _IOWATCHER_H_ +#define _IOWATCHER_H_ + +#include "ioeventdef.h" + +uvNameSpaceBegin + + +uvNameSpaceEnd + + +#endif diff --git a/asynio/iooperationimpl.cpp b/asynio/iooperationimpl.cpp index 42e7d19a680f42c736305d38f0be2be419c74e43..c18a825743b657824a62013aafb0b0c403f681ed 100644 --- a/asynio/iooperationimpl.cpp +++ b/asynio/iooperationimpl.cpp @@ -2,6 +2,8 @@ CIoOperationImpl::CIoOperationImpl() { + memset(&m_OperBehavior, 0, sizeof(OperationBehavior)); + //m_iooper.Dispatched(std::bind(&CIoOperationImpl::MsgProc, this, OP_NULL), std::bind(&CIoOperationImpl::MsgDoneProc, this, OP_NULL)); } CIoOperationImpl::~CIoOperationImpl() @@ -9,9 +11,14 @@ CIoOperationImpl::~CIoOperationImpl() } ////////////////////////////////////////////////////////////////////////// - -std_method_impl CIoOperationImpl::Bind(IIoOperationEvents* pEvent) +std_method_impl CIoOperationImpl::SetOpType(optype op) +{ + m_Opt = op; + return S_OK; +} +std_method_impl CIoOperationImpl::GetOpType(optype *op) { + *op = m_Opt; return S_OK; } std_method_impl CIoOperationImpl::SetId(ULONG lId) @@ -71,7 +78,45 @@ std_method_impl CIoOperationImpl::GetResultInterface(IBase** pOperationPos) } std_method_impl CIoOperationImpl::Cancel() { + memset(&m_OperBehavior, 0, sizeof(OperationBehavior)); + //m_iooper.Dispatched(std::bind(&CIoOperationImpl::MsgProc, this, OP_NULL), std::bind(&CIoOperationImpl::MsgDoneProc, this, OP_NULL)); + return S_OK; } +std_method_impl CIoOperationImpl::SetBind(OperationBehavior addr) +{ + memcpy(&m_OperBehavior, &addr, sizeof(OperationBehavior)); + return S_OK; +} +std_method_impl CIoOperationImpl::GetBind(OperationBehavior** addr) +{ + *addr = &m_OperBehavior; + return S_OK; +} + +void CIoOperationImpl::BindEvent(IIoOperationEvents *pEvents) +{ + m_pEvent = pEvents; +} +io_operation_t* CIoOperationImpl::GetOper() +{ + return &m_iooper; +} +std_method_type_impl(void*) CIoOperationImpl::GetPoint() +{ + return this; +} +std_method_type_impl(void*) CIoOperationImpl::GetOP() +{ + return &this->m_iooper; +} +HRESULT CIoOperationImpl::MsgProc(int type) +{ + return S_OK; +} +HRESULT CIoOperationImpl::MsgDoneProc(int type) +{ + return S_OK; +} diff --git a/asynio/iooperationimpl.h b/asynio/iooperationimpl.h index a1a30c6e1e04de9c6e7e895003b548cf11ba9781..c930ffba3d5fc55bb45529879852e7382e48ba5d 100644 --- a/asynio/iooperationimpl.h +++ b/asynio/iooperationimpl.h @@ -1,8 +1,11 @@ -#ifndef _TCPSOCKIMPL_H_ -#define _TCPSOCKIMPL_H_ +#ifndef _IOOPERATIONIMPL_H_ +#define _IOOPERATIONIMPL_H_ #include "stdafx.h" +#include "ioimpl/iooperation.h" + #include +uvNameSpace class CIoOperationImpl : public IIoOperation, public CUnknownImp @@ -11,20 +14,13 @@ class CIoOperationImpl : public IIoOperation, public: CIoOperationImpl(void); virtual ~CIoOperationImpl(void); - UNKNOWN_IMP1_MEM(IIoOperation); - - std_method_(ULONG, Release)() - { - atomicdel((LONG*)(LPVOID)&this->m_RefCount); - if (this->m_RefCount) - return this->m_RefCount; - delete this; - return 0; - } + UNKNOWN_IMP1(IIoOperation); + void BindEvent(IIoOperationEvents *pEvents); ////////////////////////////////////////////////////////////////////////// //IIoOperation - std_method(Bind)(IIoOperationEvents* pEvent); + std_method(SetOpType)(optype op); + std_method(GetOpType)(optype *op); std_method(SetId)(ULONG lId); std_method(GetId)(ULONG *pId); std_method(SetResult)(ERROR_CODE lErrorCode, @@ -42,13 +38,20 @@ public: std_method(SetResultInterface)(IBase* lOperationPos); std_method(GetResultInterface)(IBase** pOperationPos); std_method(Cancel)(); - - + std_method(SetBind)(OperationBehavior addr); + std_method(GetBind)(OperationBehavior** addr); + std_method_(void*, GetPoint)(); + std_method_(void*, GetOP)(); +protected: + HRESULT MsgProc(int type); + HRESULT MsgDoneProc(int type); +public: + io_operation_t * GetOper(); + IIoOperationEvents* m_pEvent; private: - - - - + OperationBehavior m_OperBehavior; + optype m_Opt; + io_operation_t m_iooper; }; diff --git a/asynio/iostreambase.cpp b/asynio/iostreambase.cpp deleted file mode 100644 index 5684bfc365c68eaafe53eaff7f1ccf2608dc15df..0000000000000000000000000000000000000000 --- a/asynio/iostreambase.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "iostreambase.h" \ No newline at end of file diff --git a/asynio/iostreambase.h b/asynio/iostreambase.h deleted file mode 100644 index b3f2798c44cee514e3312a45531c545978bcb53b..0000000000000000000000000000000000000000 --- a/asynio/iostreambase.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _IOSTREAMBASE_H_ -#define _IOSTREAMBASE_H_ - -#include "ioeventdef.h" - -class io_stream_t { -public: - io_stream_t() { - - } - virtual ~io_stream_t() { - - } -}; - - - -#endif diff --git a/asynio/iotcpbase.cpp b/asynio/iotcpbase.cpp deleted file mode 100644 index d25de7ed55a036cb91917f0dc75a6dd4372d4bc0..0000000000000000000000000000000000000000 --- a/asynio/iotcpbase.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include "iotcpbase.h" - -io_tcp_i::io_tcp_i() { - - tcphandler = NULL; -} - -io_tcp_i::~io_tcp_i() { - -} -int io_tcp_i::SockToIoEvent(os_sock_t sock) { - tcphandler = (uv_tcp_t*)malloc(sizeof(uv_tcp_t)); - uv_tcp_init(ioeventloop::Getioeventloop()->GetEv(), tcphandler); - return uv_tcp_open(tcphandler, sock); -} -int io_tcp_i::Connect() { - - return 1; -} -int io_tcp_i::Bind() { - - return 1; -} - diff --git a/asynio/iotcpbase.h b/asynio/iotcpbase.h deleted file mode 100644 index 28aa7be9aa5014b9ff70a93772bd113288ffe48a..0000000000000000000000000000000000000000 --- a/asynio/iotcpbase.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef _IOTCPBASE_H_ -#define _IOTCPBASE_H_ - -#include "iostreambase.h" -#include "ioeventloop.h" - - -class io_tcp_i : public io_stream_t { -public: - io_tcp_i(); - virtual ~io_tcp_i(); - int SockToIoEvent(os_sock_t sock); - int Connect(); - int Bind(); -public: - virtual int MsgProc(unsigned long msgid, WPARAM wParam, LPARAM lParam) = 0; -private: - uv_tcp_t * tcphandler; -}; - - - -#endif diff --git a/asynio/stdafx.h b/asynio/stdafx.h index a9b41c0e483b0d454054462d6159752ef75a3567..dfca9c2f2c20f89d47ce2628579fa6f108881655 100644 --- a/asynio/stdafx.h +++ b/asynio/stdafx.h @@ -2,7 +2,6 @@ // or project specific include files that are used frequently, but // are changed infrequently // - #ifndef _STDAFX_H_ #define _STDAFX_H_ diff --git a/asynio/tcpsocketimpl.cpp b/asynio/tcpsocketimpl.cpp index ee52503f6fc130cb323a2dde7ff722a9dab11920..6343c530735387097ec60a73b9464b43d9264125 100644 --- a/asynio/tcpsocketimpl.cpp +++ b/asynio/tcpsocketimpl.cpp @@ -33,10 +33,45 @@ std_method_impl CTcpSocketImpl::WriteAllIo(IIoOperation* pOperation) return hr; } +std_method_impl CTcpSocketImpl::ConnectIo(IIoOperation* pOperation) +{ + HRESULT hr = S_OK; + + OperationBehavior* OpB; + pOperation->GetBind(&OpB); + retrtpv(OpB->address, E_FAIL) + retrtpv(OpB->port, E_FAIL) + + struct sockaddr_in sin; + sin.sin_family = AF_INET; + if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(OpB->address))) { + return E_FAIL; + } + sin.sin_port = htons(OpB->port); + if (connect(m_socketFd, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { + return E_FAIL; + } + + return hr; +} +std_method_impl CTcpSocketImpl::AcceptConnect(IIoOperation* pOperation) +{ + HRESULT hr = S_OK; + + return hr; +} std_method_impl CTcpSocketImpl::CloseIo() { HRESULT hr = S_OK; +#if (TARGET_OS == OS_WINDOWS) + closesocket(m_socketFd); +#elif (TARGET_OS == OS_POSIX) + close(m_socketFd); +#endif + + + return hr; } std_method_impl CTcpSocketImpl::OpenIo() @@ -54,29 +89,6 @@ std_method_type_impl(os_sock_t) CTcpSocketImpl::GetSocket() { return m_socketFd; } -std_method_impl CTcpSocketImpl::Bind(const char* addr, unsigned int uport) -{ - HRESULT hr = S_OK; - - retrtpv(addr, E_FAIL) - retrtpv(uport, E_FAIL) - - struct sockaddr_in sin; - sin.sin_family = AF_INET; - if (INADDR_NONE == (sin.sin_addr.s_addr = inet_addr(addr))) { - return E_FAIL; - } - sin.sin_port = htons(uport); - if (connect(m_socketFd, (struct sockaddr*)(&sin), sizeof(struct sockaddr_in)) != 0) { - return E_FAIL; - } - - return hr; -} -std_method_type_impl(os_sock_t) CTcpSocketImpl::BindAccept(const char* addr, unsigned int uport, int n) -{ - return -1; -} std_method_impl CTcpSocketImpl::SetReuseAddr(bool bstart) { HRESULT hr = S_OK; @@ -133,9 +145,38 @@ std_method_impl CTcpSocketImpl::SetNoSigPipe(bool bstart) #endif - - return hr; } +std_method_impl CTcpSocketImpl::SetNonblock(bool bstart) +{ + return S_OK; +} +std_method_impl CTcpSocketImpl::SendBufLen(int size) +{ + return S_OK; +} +std_method_impl CTcpSocketImpl::RecvBufLen(int size) +{ + return S_OK; +} +std_method_impl CTcpSocketImpl::SendTime(int sec) +{ + return S_OK; +} +std_method_impl CTcpSocketImpl::RecvTime(int sec) +{ + return S_OK; +} +std_method_impl CTcpSocketImpl::SendLoWat(int size) +{ + return S_OK; +} +std_method_impl CTcpSocketImpl::RecvLoWat(int size) +{ + return S_OK; +} + + + diff --git a/asynio/tcpsocketimpl.h b/asynio/tcpsocketimpl.h index 12caec6f6655eaee9b3312a21a01d1967592c677..df0e804c8d313eaed7194c41a71ee5ac207cab91 100644 --- a/asynio/tcpsocketimpl.h +++ b/asynio/tcpsocketimpl.h @@ -18,6 +18,8 @@ public: std_method(WriteIo)(IIoOperation* pOperation); std_method(ReadAllIo)(IIoOperation* pOperation); std_method(WriteAllIo)(IIoOperation* pOperation); + std_method(ConnectIo)(IIoOperation* pOperation); + std_method(AcceptConnect)(IIoOperation* pOperation); std_method(CloseIo)(); std_method(OpenIo)(); ////////////////////////////////////////////////////////////////////////// @@ -25,14 +27,19 @@ public: std_method_(os_sock_t,GetSocket)(); ////////////////////////////////////////////////////////////////////////// //ITcpSocket - std_method(Bind)(const char* addr, unsigned int uport); - std_method_(os_sock_t, BindAccept)(const char* addr, unsigned int uport, int n); std_method(SetReuseAddr)(bool bstart); std_method(SetNoDelay)(bool bstart); std_method(SetLinger)(bool bstart); std_method(SetKeepalive)(bool bstart); std_method(SetCork)(bool bstart); std_method(SetNoSigPipe)(bool bstart); + std_method(SetNonblock)(bool bstart); + std_method(SendBufLen)(int size); + std_method(RecvBufLen)(int size); + std_method(SendTime)(int sec); + std_method(RecvTime)(int sec); + std_method(SendLoWat)(int size); + std_method(RecvLoWat)(int size); ////////////////////////////////////////////////////////////////////////// os_sock_t m_socketFd; diff --git a/bin/Debug/mainmoduleconfig.json b/bin/Debug/mainmoduleconfig.json index 0f86bee17b4f320614db923753ff5bee957bf429..450aa86a365dc0288e49a52fca45396caad8f7d2 100644 --- a/bin/Debug/mainmoduleconfig.json +++ b/bin/Debug/mainmoduleconfig.json @@ -1,52 +1,63 @@ { "commodule":{ "basecom": [ - {"components_path":"infoanalysis","clsidinclude": - [ - { - "clsid":"{E2C3154C-AFC7-4875-8BCC-CB116CA0CF45}", - "name":"json", - "start":"2", - "ui":"0", - "param":"dateui2.res" - } - ] - }, - {"components_path":"asynio","clsidinclude": - [ - { - "clsid":"{B6DDB9B0-186F-4199-A0B3-7BA5026F5888}", - "name":"asynio", - "start":"3", - "ui":"0", - "param":"dateui2.res" - } - ] - }, - {"components_path":"sshchannel","clsidinclude": - [ - { - "clsid":"{4A27FA11-BEA7-46E8-9F32-EC0C9F6E1A9E}", - "name":"sshchannel", - "start":"10", - "ui":"0", - "param":"dateui2.res" - } - ] + {"components_path":"infoanalysis","clsidinclude": + [ + { + "clsid":"{E2C3154C-AFC7-4875-8BCC-CB116CA0CF45}", + "name":"json", + "start":"2", + "ui":"0", + "param":"dateui2.res" } + ] + }, + {"components_path":"asynio","clsidinclude": + [ + { + "clsid":"{F170A724-AACA-4603-BB1C-0A8EAF1C3322}", + "name":"asynframe", + "start":"11", + "ui":"0", + "param":"dateui2.res" + } + ] + }, + {"components_path":"protocol","clsidinclude": + [ + { + "clsid":"{ED660EF7-7D0B-4CBE-8D92-D5F225434464}", + "name":"http", + "start":"71", + "ui":"0", + "param":"dateui2.res" + } + ] + }, + {"components_path":"sshchannel","clsidinclude": + [ + { + "clsid":"{4A27FA11-BEA7-46E8-9F32-EC0C9F6E1A9E}", + "name":"sshchannel", + "start":"100", + "ui":"0", + "param":"dateui2.res" + } + ] + } ], "maincom": {"components_path":"comenv","clsidinclude": - [ - { - "clsid":"{C8CA7580-8E65-49e6-A66A-B087C7EF523D}", - "name":"main", - "start":"1", - "ui":"0", - "param":"dateui2.res" - - } - ] + [ + { + "clsid":"{C8CA7580-8E65-49e6-A66A-B087C7EF523D}", + "name":"main", + "start":"1", + "ui":"0", + "param":"dateui2.res" + + } + ] } }, @@ -63,6 +74,5 @@ "exittime":400000, "permission": "min", "username":"local" - } - -} + } +} \ No newline at end of file diff --git a/bin/mainmoduleconfig.json b/bin/mainmoduleconfig.json index f1dda6afad6d35b20ef0cdbfc5b325d04b32e7e3..450aa86a365dc0288e49a52fca45396caad8f7d2 100644 --- a/bin/mainmoduleconfig.json +++ b/bin/mainmoduleconfig.json @@ -2,51 +2,62 @@ "commodule":{ "basecom": [ {"components_path":"infoanalysis","clsidinclude": - [ - { - "clsid":"{E2C3154C-AFC7-4875-8BCC-CB116CA0CF45}", - "name":"json", - "start":"2", - "ui":"0", - "param":"dateui2.res" - } - ] + [ + { + "clsid":"{E2C3154C-AFC7-4875-8BCC-CB116CA0CF45}", + "name":"json", + "start":"2", + "ui":"0", + "param":"dateui2.res" + } + ] }, {"components_path":"asynio","clsidinclude": - [ - { - "clsid":"{B6DDB9B0-186F-4199-A0B3-7BA5026F5888}", - "name":"asynio", - "start":"3", - "ui":"0", - "param":"dateui2.res" - } - ] + [ + { + "clsid":"{F170A724-AACA-4603-BB1C-0A8EAF1C3322}", + "name":"asynframe", + "start":"11", + "ui":"0", + "param":"dateui2.res" + } + ] + }, + {"components_path":"protocol","clsidinclude": + [ + { + "clsid":"{ED660EF7-7D0B-4CBE-8D92-D5F225434464}", + "name":"http", + "start":"71", + "ui":"0", + "param":"dateui2.res" + } + ] }, {"components_path":"sshchannel","clsidinclude": - [ - { - "clsid":"{4A27FA11-BEA7-46E8-9F32-EC0C9F6E1A9E}", - "name":"sshchannel", - "start":"10", - "ui":"0", - "param":"dateui2.res" - } - ] + [ + { + "clsid":"{4A27FA11-BEA7-46E8-9F32-EC0C9F6E1A9E}", + "name":"sshchannel", + "start":"100", + "ui":"0", + "param":"dateui2.res" + } + ] } ], "maincom": {"components_path":"comenv","clsidinclude": - [ - { - "clsid":"{C8CA7580-8E65-49e6-A66A-B087C7EF523D}", - "name":"main", - "start":"1", - "ui":"0", - "param":"dateui2.res" - - } - ] + [ + { + "clsid":"{C8CA7580-8E65-49e6-A66A-B087C7EF523D}", + "name":"main", + "start":"1", + "ui":"0", + "param":"dateui2.res" + + } + ] } }, @@ -63,6 +74,5 @@ "exittime":400000, "permission": "min", "username":"local" - } - -} + } +} \ No newline at end of file diff --git a/comenv/comenv.cpp b/comenv/comenv.cpp index bbfa0c30fc8bf44c44d49b9e931dd933f635ae32..c4c9b76d51762b488ab8afd50f543bc440f6b6d3 100644 --- a/comenv/comenv.cpp +++ b/comenv/comenv.cpp @@ -354,7 +354,8 @@ HRESULT ComEnv::loadOlAndRot() if(pUnknownEnv) RFAILED(m_pRot->Register(CLSID_ComEnv, pUnknownEnv)); - tstring strComEnv = m_strRunPath + ENVCOM; + + tstring strComEnv = ModuleToPath(_T("comenv"));; m_pOlManager->Register(CLSID_CObjectLoader, strComEnv.c_str(), (LPVOID)DllGetClassObject); m_pOlManager->Register(ClSID_CRunningObjectTable, strComEnv.c_str(), (LPVOID)DllGetClassObject); @@ -382,9 +383,7 @@ HRESULT ComEnv::loadConfigModule(bool bUseEnumObject) CComLoader xmlLoader; _lComPtr pInfoAnalysis; - tstring curpath = GetCurrentRunPath(m_hInstance); - - curpath += DEFAULT_ANALYSISLIB; + tstring curpath = ModuleToPath(_T("infoanalysis")); BOOL bLoad = xmlLoader.LoadCom(curpath.c_str()); if(!bLoad) diff --git a/extensions/include/io/iasynio.h b/extensions/include/io/iasynio.h index cbaa92470770917747aafa3249424c53527c9820..369338840fc94caa25799ce62b54494b83b0c765 100644 --- a/extensions/include/io/iasynio.h +++ b/extensions/include/io/iasynio.h @@ -23,9 +23,5 @@ interface IAsynIo : public IBase }; _DEFINE_IID(IAsynIo, "{91559897-31F2-46C1-85AB-1ED97D58EE7B}"); -// {B6DDB9B0-186F-4199-A0B3-7BA5026F5888} -_DEFINE_GUID(CLSID_IAsynIo, - 0xb6ddb9b0, 0x186f, 0x4199, 0xa0, 0xb3, 0x7b, 0xa5, 0x2, 0x6f, 0x58, 0x88); - #endif // !_ASYNIO_H_ \ No newline at end of file diff --git a/extensions/include/io/ievent.h b/extensions/include/io/iframe.h similarity index 33% rename from extensions/include/io/ievent.h rename to extensions/include/io/iframe.h index 98e392f41fb19d830d1b93ea7a60a99c0f460923..1ee3142317c6b159a0b528388136a3d6acac5e26 100644 --- a/extensions/include/io/ievent.h +++ b/extensions/include/io/iframe.h @@ -4,42 +4,25 @@ #include - -interface IMessageEvents : public IBase +interface IAsynFrame : public IBase { - std_method(OnMessage)(ULONG lMessageId, ULONG lParam1, ULONG lParam2) = 0; - std_method(OnDeleteMessage)(ULONG lMessageId, ULONG lParam1, ULONG lParam2) = 0; -}; -_DEFINE_IID(IMessageEvents, "{004BB07B-5B97-4BA3-A16B-4113F00E6F85}"); - -interface IEventBase : public IBase -{ - std_method(AttachMessageEvents)(IMessageEvents *pEvents) = 0; - std_method(DetachMessageEvents)(IMessageEvents *pEvents) = 0; - std_method(SendMessage)(IMessageEvents *pEvents, - ULONG lMessageId, - ULONG lParam1, - ULONG lParam2) = 0; - std_method(PostMessage)(IMessageEvents *pEvents, - ULONG lMessageId, - ULONG lParam1, - ULONG lParam2) = 0; std_method(AddTimer)(ITimerEvents *pEvents, ULONG lTimerId, ULONG lMilliSecond, BOOL bCycled) = 0; - std_method(DelTimer)(ITimerEvents *pEvents,ULONG lTimerId) = 0; std_method(ClearTimer)(ITimerEvents *pEvents) = 0; - std_method(CreateAsynIoOperation)(IIoOperation **ppOperation) = 0; - std_method(PostAsynIoOperation)(IIoOperation *pOperation) = 0; + std_method(CreateAsynIoOperation)( IIoOperation **ppOperation, + IIoOperationEvents* pEvent) = 0; + std_method(PostAsynIoOperation)(IIoOperation *pOperation) = 0; + }; -_DEFINE_IID(IEventBase, "{1351D756-958E-4DE5-86C6-9280AC49E672}"); +_DEFINE_IID(IAsynFrame, "{1351D756-958E-4DE5-86C6-9280AC49E672}"); // {F170A724-AACA-4603-BB1C-0A8EAF1C3322} -_DEFINE_GUID(CLSID_EventBase, +_DEFINE_GUID(CLSID_IAsynFrame, 0xf170a724, 0xaaca, 0x4603, 0xbb, 0x1c, 0xa, 0x8e, 0xaf, 0x1c, 0x33, 0x22); #endif \ No newline at end of file diff --git a/extensions/include/io/iiodevice.h b/extensions/include/io/iiodevice.h index 69b80c9f1e331cf74e835ea71bf3ebc6818dd14e..030407cd963dc7385bc0b458ca4dce710c8960f8 100644 --- a/extensions/include/io/iiodevice.h +++ b/extensions/include/io/iiodevice.h @@ -7,6 +7,8 @@ interface IIoDevice : public IBase std_method(WriteIo)(IIoOperation* pOperation) = 0; std_method(ReadAllIo)(IIoOperation* pOperation) = 0; std_method(WriteAllIo)(IIoOperation* pOperation) = 0; + std_method(ConnectIo)(IIoOperation* pOperation) = 0; + std_method(AcceptConnect)(IIoOperation* pOperation) = 0; std_method(CloseIo)() = 0; std_method(OpenIo)() = 0; }; diff --git a/extensions/include/io/ioperation.h b/extensions/include/io/ioperation.h index ab44b3ac08858033b4501091a33d906279937e44..f08ccd039a979fd81305e726c99d0e2a33f9fd59 100644 --- a/extensions/include/io/ioperation.h +++ b/extensions/include/io/ioperation.h @@ -3,14 +3,77 @@ typedef ULONG ERROR_CODE; -typedef BYTE *BUFFER_PTR; +typedef BYTE* BUFFER_PTR; typedef ULONG BUFFER_SIZE; -interface IIoOperationEvents; +// Do not use LIBUV files and pipe operations +// Because the encapsulation is a little bit inappropriate. +// Re-encapsulation of an IO framework for file operations + + +#pragma pack(1) + +typedef enum TagAddrType { + addr_socket_v4 = 0, + addr_socket_v6 = 1, + addr_file = 2, + addr_pipe = 3 +}AddrType; + + +typedef struct TagOperationBehavior +{ + AddrType type; + char address[128]; + unsigned int port; + union { + os_sock_t socket; + os_fd_t fd; + os_pipe_t pipe; + }Object; +}OperationBehavior; + + +enum optype { + + OP_NULL = 0, + OP_TCPSOCKET_CONNECT, + OP_TCPSOCKET_CONNECT_DONE, + OP_TCPSOCKET_RECV, + OP_TCPSOCKET_SEND, + OP_TCPSOCKET_ACCEPT, + OP_TCPSOCKET_BIND, + + OP_UDPSOCKET_RECV, + OP_UDPSOCKET_SEND, + OP_UDPSOCKET_BIND, + + OP_FILE = 100, + OP_FILE_ALLOC_SIZE, + OP_FILE_READ, + OP_FILE_WRITE, + OP_FILE_FLUSH, + OP_FILE_RESIZE, + OP_FAST_READ, + OP_FAST_WRITE, + + OP_DNS = 201, + + OP_EXCEPTION = 1000, + FILE_EXCEPTION, + PROXY_EXCEPTION, + SOCKET_EXCEPTION, + UNKNOWN_EXCEPTION, + OP_NOTIFY_EXIT, + OP_CANCEL + +}; +#pragma pack() interface IIoOperation : public IBase { - std_method(Bind)(IIoOperationEvents* pEvent) = 0; + std_method(SetOpType)(optype op) = 0; + std_method(GetOpType)(optype *op) = 0; std_method(SetId)(ULONG lId) = 0; std_method(GetId)(ULONG *pId) = 0; std_method(SetResult)(ERROR_CODE lErrorCode, @@ -21,22 +84,26 @@ interface IIoOperation : public IBase std_method(GetBuffer)(BUFFER_PTR *ppBuffer, BUFFER_SIZE *pBufferSize) = 0; std_method(ReleaseBuffer)() = 0; - std_method(SetIoParam)(ULONG lIoStartPos,ULONG lIoExpectBytes) = 0; - std_method(GetIoParam)(ULONG* pIoStartPos,ULONG* pIoExpectBytes) = 0; - std_method(SetOperationPos)(ULONGLONG lOperationPos) = 0; - std_method(GetOperationPos)(ULONGLONG* pOperationPos) = 0; + std_method(SetIoParam)(ULONG lIoStartPos, ULONG lIoExpectBytes) = 0; + std_method(GetIoParam)(ULONG* pIoStartPos, ULONG* pIoExpectBytes) = 0; std_method(SetResultInterface)(IBase* lOperationPos) = 0; std_method(GetResultInterface)(IBase** pOperationPos) = 0; std_method(Cancel)() = 0; - + std_method(SetBind)(OperationBehavior addr) = 0; + std_method(GetBind)(OperationBehavior** addr) = 0; + std_method_(void*,GetPoint)() = 0; + std_method_(void*, GetOP)() = 0; }; + + _DEFINE_IID(IIoOperation, "{D34BE927-B63E-4B0C-9BE7-D4E123A05B2B}"); -interface IIoOperationEvents : public IBase + +interface IIoOperationEvents { std_method(OnOperationComplete)(IIoOperation *pOperation) = 0; }; -_DEFINE_IID(IIoOperationEvents, "{2D2E1C66-AB07-430F-9C9A-AF9855AC7071}"); +//_DEFINE_IID(IIoOperationEvents, "{2D2E1C66-AB07-430F-9C9A-AF9855AC7071}"); #endif \ No newline at end of file diff --git a/extensions/include/io/isocket.h b/extensions/include/io/isocket.h index 49e57891ed6ec0413afd8612cef7e52729d16ef4..e100ce03ccd5ec7e868a3c99b26a02e420684712 100644 --- a/extensions/include/io/isocket.h +++ b/extensions/include/io/isocket.h @@ -13,26 +13,24 @@ _DEFINE_IID(ISocket, "{B3F9D677-0489-4B9D-B2FB-E48F6B0E2E68}"); interface ITcpSocket : public ISocket { - std_method(Bind)(const char* addr, unsigned int uport) = 0; - std_method_(os_sock_t, BindAccept)(const char* addr, unsigned int uport, int n) = 0; - std_method(SetReuseAddr)(bool bstart) = 0; - std_method(SetNoDelay)(bool bstart) = 0; - std_method(SetLinger)(bool bstart) = 0; - std_method(SetKeepalive)(bool bstart) = 0; - std_method(SetCork)(bool bstart) = 0; - std_method(SetNoSigPipe)(bool bstart) = 0; + std_method(SetReuseAddr)(bool bstart) = 0; + std_method(SetNoDelay)(bool bstart) = 0; + std_method(SetLinger)(bool bstart) = 0; + std_method(SetKeepalive)(bool bstart) = 0; + std_method(SetCork)(bool bstart) = 0; + std_method(SetNoSigPipe)(bool bstart) = 0; + std_method(SetNonblock)(bool bstart) = 0; + std_method(SendBufLen)(int size) = 0; + std_method(RecvBufLen)(int size) = 0; + std_method(SendTime)(int sec) = 0; + std_method(RecvTime)(int sec) = 0; + std_method(SendLoWat)(int size) = 0; + std_method(RecvLoWat)(int size) = 0; }; _DEFINE_IID(ITcpSocket, "{6F7C433A-D7C5-4EFB-A525-701A675D7388}"); interface IAsyncTcpSocket : public ITcpSocket { - std_method(SetNonblock)(bool bstart) = 0; - std_method(SendBufLen)(int size) = 0; - std_method(RecvBufLen)(int size) = 0; - std_method(SendTime)(int sec) = 0; - std_method(RecvTime)(int sec) = 0; - std_method(SendLoWat)(int size) = 0; - std_method(RecvLoWat)(int size) = 0; }; diff --git a/extensions/include/protocol/ihttp.h b/extensions/include/protocol/ihttp.h new file mode 100644 index 0000000000000000000000000000000000000000..01a0f9d74ac06c187e78baabe7d261fae7bf1e96 --- /dev/null +++ b/extensions/include/protocol/ihttp.h @@ -0,0 +1,33 @@ +#ifndef _PROTOCOL_HTTP_H_ +#define _PROTOCOL_HTTP_H_ + + + +interface IHttp : public IBase +{ + std_method(Get)() = 0; + std_method(Post)() = 0; +}; + +_DEFINE_IID(IHttp, "{B8D1828A-F5CF-4358-9848-6F59AD5C0B49}"); + + +interface IHttpSrv : public IBase +{ + std_method(Post)() = 0; +}; +_DEFINE_IID(IHttpSrv, "{47DF9098-26A7-4C75-91A7-68D320594807}"); + + +interface IHttpCreator : public IBase +{ + std_method(CreateHttpClient)(IBase **pBase) = 0; + std_method(CreateHttpServer)(IBase **pBase) = 0; + +}; +_DEFINE_IID(IHttpCreator, "{B39B6827-EE35-4900-AF0F-4E50C556A681}"); + +// {ED660EF7-7D0B-4CBE-8D92-D5F225434464} +_DEFINE_GUID(CLSID_IHttp, + 0xed660ef7, 0x7d0b, 0x4cbe, 0x8d, 0x92, 0xd5, 0xf2, 0x25, 0x43, 0x44, 0x64); +#endif \ No newline at end of file diff --git a/include/compat/getpath.hpp b/include/compat/getpath.hpp index 3ed36ffe8f6175dbf978c6594a7ab7d3e352ffea..9b3588d2209c7ef69d1d76bea523f5a3b8f17897 100644 --- a/include/compat/getpath.hpp +++ b/include/compat/getpath.hpp @@ -127,6 +127,7 @@ inline static tstring ModNameToModPath(const TCHAR* pName) stringpath += _T("//"); stringpath += _T("lib"); #endif // __GNUC__ + stringpath += pName; #ifdef _MSC_VER stringpath += _T(".dll"); diff --git a/include/compat/queue.h b/include/compat/queue.h new file mode 100644 index 0000000000000000000000000000000000000000..3e917c3f9653c08d3032ef245ec9820cb35d05cd --- /dev/null +++ b/include/compat/queue.h @@ -0,0 +1,91 @@ +#ifndef _COMPAT_QUEUE_H_ +#define _COMPAT_QUEUE_H_ + + +#include + +typedef void *_QUEUE[2]; + +#define _QUEUE_NEXT(q) (*(_QUEUE **) &((*(q))[0])) +#define _QUEUE_PREV(q) (*(_QUEUE **) &((*(q))[1])) +#define _QUEUE_PREV_NEXT(q) (_QUEUE_NEXT(_QUEUE_PREV(q))) +#define _QUEUE_NEXT_PREV(q) (_QUEUE_PREV(_QUEUE_NEXT(q))) + +#define _QUEUE_DATA(ptr, type, field) \ + ((type *) ((char *) (ptr) - offsetof(type, field))) + + +#define _QUEUE_FOREACH(q, h) \ + for ((q) = _QUEUE_NEXT(h); (q) != (h); (q) = _QUEUE_NEXT(q)) + +#define _QUEUE_EMPTY(q) \ + ((const _QUEUE *) (q) == (const _QUEUE *) _QUEUE_NEXT(q)) + +#define _QUEUE_HEAD(q) \ + (_QUEUE_NEXT(q)) + +#define _QUEUE_INIT(q) \ + do { \ + _QUEUE_NEXT(q) = (q); \ + _QUEUE_PREV(q) = (q); \ + } \ + while (0) + +#define _QUEUE_ADD(h, n) \ + do { \ + _QUEUE_PREV_NEXT(h) = _QUEUE_NEXT(n); \ + _QUEUE_NEXT_PREV(n) = _QUEUE_PREV(h); \ + _QUEUE_PREV(h) = _QUEUE_PREV(n); \ + _QUEUE_PREV_NEXT(h) = (h); \ + } \ + while (0) + +#define _QUEUE_SPLIT(h, q, n) \ + do { \ + _QUEUE_PREV(n) = _QUEUE_PREV(h); \ + _QUEUE_PREV_NEXT(n) = (n); \ + _QUEUE_NEXT(n) = (q); \ + _QUEUE_PREV(h) = _QUEUE_PREV(q); \ + _QUEUE_PREV_NEXT(h) = (h); \ + _QUEUE_PREV(q) = (n); \ + } \ + while (0) + +#define _QUEUE_MOVE(h, n) \ + do { \ + if (_QUEUE_EMPTY(h)) \ + _QUEUE_INIT(n); \ + else { \ + _QUEUE* q = _QUEUE_HEAD(h); \ + _QUEUE_SPLIT(h, q, n); \ + } \ + } \ + while (0) + +#define _QUEUE_INSERT_HEAD(h, q) \ + do { \ + _QUEUE_NEXT(q) = _QUEUE_NEXT(h); \ + _QUEUE_PREV(q) = (h); \ + _QUEUE_NEXT_PREV(q) = (q); \ + _QUEUE_NEXT(h) = (q); \ + } \ + while (0) + +#define _QUEUE_INSERT_TAIL(h, q) \ + do { \ + _QUEUE_NEXT(q) = (h); \ + _QUEUE_PREV(q) = _QUEUE_PREV(h); \ + _QUEUE_PREV_NEXT(q) = (q); \ + _QUEUE_PREV(h) = (q); \ + } \ + while (0) + +#define _QUEUE_REMOVE(q) \ + do { \ + _QUEUE_PREV_NEXT(q) = _QUEUE_NEXT(q); \ + _QUEUE_NEXT_PREV(q) = _QUEUE_PREV(q); \ + } \ + while (0) + + +#endif \ No newline at end of file diff --git a/include/compat/slice.h b/include/compat/slice.h new file mode 100644 index 0000000000000000000000000000000000000000..0c2a7b3dbd5b917307fa2bf396deeb38f9c37289 --- /dev/null +++ b/include/compat/slice.h @@ -0,0 +1,126 @@ +// Copyright (c) 2011 The LevelDB Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. See the AUTHORS file for names of contributors. +// +// Slice is a simple structure containing a pointer into some external +// storage and a size. The user of a Slice must ensure that the slice +// is not used after the corresponding external storage has been +// deallocated. +// +// Multiple threads can invoke const methods on a Slice without +// external synchronization, but if any of the threads may call a +// non-const method, all threads accessing the same Slice must use +// external synchronization. + +#pragma once + +#include +#include +#include + +// Copy from leveldb project +// @see https://github.com/google/leveldb/blob/master/include/leveldb/slice.h + +class Slice { +public: + typedef char value_type; + +public: + // Create an empty slice. + Slice() : data_(""), size_(0) {} + + // Create a slice that refers to d[0,n-1]. + Slice(const char* d, size_t n) : data_(d), size_(n) {} + + // Create a slice that refers to the contents of "s" + Slice(const std::string& s) : data_(s.data()), size_(s.size()) {} + + // Create a slice that refers to s[0,strlen(s)-1] + Slice(const char* s) : data_(s), size_(strlen(s)) {} + + // Return a pointer to the beginning of the referenced data + const char* data() const { + return data_; + } + + // Return the length (in bytes) of the referenced data + size_t size() const { + return size_; + } + + // Return true if the length of the referenced data is zero + bool empty() const { + return size_ == 0; + } + + // Return the ith byte in the referenced data. + // REQUIRES: n < size() + char operator[](size_t n) const { + assert(n < size()); + return data_[n]; + } + + // Change this slice to refer to an empty array + void clear() { + data_ = ""; + size_ = 0; + } + + // Drop the first "n" bytes from this slice. + void remove_prefix(size_t n) { + assert(n <= size()); + data_ += n; + size_ -= n; + } + + // Return a string that contains the copy of the referenced data. + std::string ToString() const { + return std::string(data_, size_); + } + + // Three-way comparison. Returns value: + // < 0 if "*this" < "b", + // == 0 if "*this" == "b", + // > 0 if "*this" > "b" + int compare(const Slice& b) const; + +private: + const char* data_; + size_t size_; +}; + +typedef Slice slice; + +//--------------------------------------------------------- +//typedef Map SliceSliceMap; +//--------------------------------------------------------- + +inline bool operator==(const Slice& x, const Slice& y) { + return ((x.size() == y.size()) && + (memcmp(x.data(), y.data(), x.size()) == 0)); +} + +inline bool operator!=(const Slice& x, const Slice& y) { + return !(x == y); +} + +inline bool operator<(const Slice& x, const Slice& y) { + return x.compare(y) < 0; +} + + +inline int Slice::compare(const Slice& b) const { + const size_t min_len = (size_ < b.size_) ? size_ : b.size_; + int r = memcmp(data_, b.data_, min_len); + + if (r == 0) { + if (size_ < b.size_) { + r = -1; + } else if (size_ > b.size_) { + r = +1; + } + } + + return r; +} + diff --git a/include/compat/thread.hpp b/include/compat/thread.hpp new file mode 100644 index 0000000000000000000000000000000000000000..f6e8142b966c12eb536c4069e4fd9bcfb9da4d9b --- /dev/null +++ b/include/compat/thread.hpp @@ -0,0 +1,53 @@ + +#ifndef _COMPAT_THREAD_ +#define _COMPAT_THREAD_ + +#include +#include +#include + + +class ithread +{ +public: + ithread() { + + } + virtual ~ithread() { + + } + bool start_thread() { + + //m_thread_.reset(new std::thread(std::bind(&ithread::thread_proc, this,this))); + + + os_thread_create(&thread, ithread::thread_proc,this); + return true; + } + + bool stop_thread() { + this->threadstop(); + return true; + } + bool join() { + + + return true; + } + static void thread_proc(void* pthis) { + + ithread* p = static_cast(pthis); + p->run(); + + } + +protected: + virtual void run() = 0; + virtual void threadstop() = 0; + //std::shared_ptr m_thread_; + //std::thread::id m_tid_; + //std::mutex m_mutex_; + os_thread_t thread; +}; + +#endif diff --git a/include/compat/time/duration.h b/include/compat/time/duration.h new file mode 100644 index 0000000000000000000000000000000000000000..d113c6a5c2ea75f2b18678172823d17c1e61a922 --- /dev/null +++ b/include/compat/time/duration.h @@ -0,0 +1,55 @@ +#ifndef _COMPAT_DURATION_H_ +#define _COMPAT_DURATION_H_ + + + + +class Duration { + +public: + int64_t kNanosecond; // = 1LL + int64_t kMicrosecond;// = 1000 + int64_t kMillisecond;// = 1000 * kMicrosecond + int64_t kSecond; // = 1000 * kMillisecond + int64_t kMinute; // = 60 * kSecond + int64_t kHour; // = 60 * kMinute +public: + Duration(); + explicit Duration(const struct timeval& t); + explicit Duration(int64_t nanoseconds); + explicit Duration(int nanoseconds); + explicit Duration(double seconds); + + int64_t Nanoseconds() const; + double Seconds() const; + + double Milliseconds() const; + double Microseconds() const; + double Minutes() const; + double Hours() const; + + struct timeval TimeVal() const; + void To(struct timeval* t) const; + + bool IsZero() const; + bool operator< (const Duration& rhs) const; + bool operator<=(const Duration& rhs) const; + bool operator> (const Duration& rhs) const; + bool operator>=(const Duration& rhs) const; + bool operator==(const Duration& rhs) const; + + Duration operator+=(const Duration& rhs); + Duration operator-=(const Duration& rhs); + Duration operator*=(int ns); + Duration operator/=(int ns); + +private: + void Init(); +private: + int64_t ns_; +}; + +#include "duration.inl.h" + +#endif + diff --git a/include/compat/time/duration.inl.h b/include/compat/time/duration.inl.h new file mode 100644 index 0000000000000000000000000000000000000000..f2b6c3da7eb6802b384b08cf7380bf807e315ea1 --- /dev/null +++ b/include/compat/time/duration.inl.h @@ -0,0 +1,117 @@ +#ifndef _COMPAT_DURATION_INL_H_ +#define _COMPAT_DURATION_INL_H_ + + +#include "duration.h" + + +inline Duration::Duration() + : ns_(0) { +} + +inline Duration::Duration(const struct timeval& t) + : ns_(t.tv_sec * kSecond + t.tv_usec * kMicrosecond) { +} + +inline Duration::Duration(int64_t nanoseconds) + : ns_(nanoseconds) { +} + +inline Duration::Duration(int nanoseconds) + : ns_(nanoseconds) { +} + +inline Duration::Duration(double seconds) + : ns_((int64_t)(seconds * kSecond)) { +} +inline void Duration::Init() { + + kNanosecond = 1LL; + kMicrosecond = 1000 * kNanosecond; + kMillisecond = 1000 * kMicrosecond; + kSecond = 1000 * kMillisecond; + kMinute = 60 * kSecond; + kHour = 60 * kMinute; + +} +inline int64_t Duration::Nanoseconds() const { + return ns_; +} + +inline double Duration::Seconds() const { + return double(ns_) / kSecond; +} + +inline double Duration::Milliseconds() const { + return double(ns_) / kMillisecond; +} + +inline double Duration::Microseconds() const { + return double(ns_) / kMicrosecond; +} + +inline double Duration::Minutes() const { + return double(ns_) / kMinute; +} + +inline double Duration::Hours() const { + return double(ns_) / kHour; +} + +inline bool Duration::IsZero() const { + return ns_ == 0; +} + +inline struct timeval Duration::TimeVal() const { + struct timeval t; + To(&t); + return t; +} + +inline void Duration::To(struct timeval* t) const { + t->tv_sec = (long)(ns_ / kSecond); + t->tv_usec = (long)(ns_ % kSecond) / (long)kMicrosecond; +} + +inline bool Duration::operator<(const Duration& rhs) const { + return ns_ < rhs.ns_; +} + +inline bool Duration::operator<=(const Duration& rhs) const { + return ns_ <= rhs.ns_; +} + +inline bool Duration::operator>(const Duration& rhs) const { + return ns_ > rhs.ns_; +} + +inline bool Duration::operator>=(const Duration& rhs) const { + return ns_ >= rhs.ns_; +} + +inline bool Duration::operator==(const Duration& rhs) const { + return ns_ == rhs.ns_; +} + +inline Duration Duration::operator+=(const Duration& rhs) { + ns_ += rhs.ns_; + return *this; +} + +inline Duration Duration::operator-=(const Duration& rhs) { + ns_ -= rhs.ns_; + return *this; +} + +inline Duration Duration::operator*=(int n) { + ns_ *= n; + return *this; +} + +inline Duration Duration::operator/=(int n) { + ns_ /= n; + return *this; +} + +#endif + diff --git a/include/compat/time/timestamp.h b/include/compat/time/timestamp.h new file mode 100644 index 0000000000000000000000000000000000000000..dcf1a8ed06126dca6fff2393d2d6fdfe2709db59 --- /dev/null +++ b/include/compat/time/timestamp.h @@ -0,0 +1,3 @@ +#pragma once + +#include "duration.h" diff --git a/include/compat/time/timestamp.inl.h b/include/compat/time/timestamp.inl.h new file mode 100644 index 0000000000000000000000000000000000000000..3f59c932d39b02caf58f2abac65bdd9246f0a7da --- /dev/null +++ b/include/compat/time/timestamp.inl.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/include/dlcom/byunknown.hpp b/include/dlcom/byunknown.hpp index 3217bcb766c3fb05d850bb06e77fe6d8beab57fb..6fc45e6d797558ca66cc1a619e88cedc645715d7 100644 --- a/include/dlcom/byunknown.hpp +++ b/include/dlcom/byunknown.hpp @@ -81,19 +81,20 @@ typedef long HRESULT; #endif -#define IBase ISupports -#define INULL ((ISupports*)0) -interface ISupports + +interface IBaseUnknown { std_method(QueryInterface)(const IID & riid, void **ppv) = 0; std_method_(ULONG, AddRef)() = 0; std_method_(ULONG, Release)() = 0; }; -_DEFINE_IID(ISupports, "{00000000-0000-0000-C000-000000000046}"); +_DEFINE_IID(IBaseUnknown, "{00000000-0000-0000-C000-000000000046}"); +#define IBase IBaseUnknown +#define INULL ((IBaseUnknown*)0) -interface IClassFactory__ : public ISupports +interface IClassFactory__ : public IBaseUnknown { std_method_(HRESULT, CreateInstance)(IBase *pUnkOuter, REFIID riid,void **ppvObject) = 0; std_method_(HRESULT, LockServer)(BOOL fLock) = 0; diff --git a/include/dlcom/propvariant.h b/include/dlcom/propvariant.h index e4947798303bf901c717531d4e243fd05d0b3c4b..44616858b04ab570e3a69a7b1e65331e6e569117 100644 --- a/include/dlcom/propvariant.h +++ b/include/dlcom/propvariant.h @@ -136,7 +136,7 @@ struct tagPROPVARIANT BSTR bstrVal; LPSTR pszVal; LPWSTR pwszVal; - ISupports *punkVal; + IBase *punkVal; LPSAFEARRAY parray; CAC cac; CAUB caub; @@ -165,7 +165,7 @@ struct tagPROPVARIANT DOUBLE *pdblVal; VARIANT_BOOL *pboolVal; SCODE *pscode; - ISupports **ppunkVal; + IBase **ppunkVal; }; }; diff --git a/include/util/common.hpp b/include/util/common.hpp index 202ffb9effb6d7fbbe32e5d87755143b4ce7e5a4..60db24a528a60a3c1f19314a070a286895d2b7dc 100644 --- a/include/util/common.hpp +++ b/include/util/common.hpp @@ -146,6 +146,8 @@ #define _T(x) x #endif #endif + + # define CPP_INLINE inline #else #define Memory_Allocate malloc #define STDNOTHROW diff --git a/include/util/debugbk.hpp b/include/util/debugbk.hpp index 0aaad9d9359be1f9f6551c59ee3711178ba6c2a2..584fd95675c16b2cc9d1e281390c7ed36315882e 100644 --- a/include/util/debugbk.hpp +++ b/include/util/debugbk.hpp @@ -5,13 +5,11 @@ inline static void WaitDebug() { - #if (TARGET_OS == OS_WINDOWS) DebugBreak(); #elif (TARGET_OS == OS_POSIX) asm("int3"); #endif - } diff --git a/include/util/iosprintf.hpp b/include/util/iosprintf.hpp new file mode 100644 index 0000000000000000000000000000000000000000..2e94508849014070750f949708b153565ef18571 --- /dev/null +++ b/include/util/iosprintf.hpp @@ -0,0 +1,12 @@ +#ifndef _IOSPRINTF_H_ +#define _IOSPRINTF_H_ + +#include + +#if (TARGET_OS == OS_WINDOWS) + #define iosprintf(x) OutputDebugStringA(x); +#elif (TARGET_OS == OS_POSIX) + #define iosprintf(x) printf("%s\n",x); +#endif + +#endif \ No newline at end of file diff --git a/include/util/lockex.hpp b/include/util/lockex.hpp index e87e882f21574bf8c8bf7c1a571f2a0e02b034b6..a4c4475dc4a0256718a007c5a2ee283cb8cbea92 100644 --- a/include/util/lockex.hpp +++ b/include/util/lockex.hpp @@ -3,28 +3,62 @@ #include +#if (TARGET_OS == OS_POSIX) + #define ATOM_CAS(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) + #define ATOM_CAS16(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) + #define ATOM_CAS_POINTER(ptr, oval, nval) __sync_bool_compare_and_swap(ptr, oval, nval) + #define ATOM_INC(ptr) __sync_add_and_fetch(ptr, 1) + #define ATOM_FINC(ptr) __sync_fetch_and_add(ptr, 1) + #define ATOM_DEC(ptr) __sync_sub_and_fetch(ptr, 1) + #define ATOM_FDEC(ptr) __sync_fetch_and_sub(ptr, 1) + #define ATOM_ADD(ptr,n) __sync_add_and_fetch(ptr, n) + #define ATOM_SUB(ptr,n) __sync_sub_and_fetch(ptr, n) + #define ATOM_AND(ptr,n) __sync_and_and_fetch(ptr, n) +#elif (TARGET_OS == OS_WINDOWS) + #define ATOM_INC(ptr) InterlockedIncrement((ptr)) + #define ATOM_DEC(ptr) InterlockedDecrement((ptr)) + #define ATOM_ADD(ptr,n) InterlockedAdd(ptr, n) + #define ATOM_AND(ptr,n) InterlockedAnd(ptr,n) + #define ATOM_CAS_POINTER(ptr, oval, nval) InterlockedCompareExchangePointer(ptr, nval, oval)//log + #define ATOM_CAS(ptr, oval, nval) (InterlockedCompareExchange(ptr, nval, oval)!=nval) + #define ATOM_CAS16(ptr, oval, nval) (InterlockedCompareExchange16(ptr, nval, oval)!=nval) + #define ATOM_FINC(ptr) InterlockedIncrement((ptr)) + #define ATOM_SUB(ptr,n) InterlockedExchangeAdd(ptr,-(ssize_t)(n)) +#endif -inline static long atomicadd(long* lpAddend){ + + +inline static long atomicadd(LONG* lpAddend){ + + /* #if (TARGET_OS == OS_WINDOWS) return InterlockedIncrement(lpAddend); #elif (TARGET_OS == OS_POSIX) return __sync_add_and_fetch(lpAddend,1); - #endif + #endif*/ + + return ATOM_ADD(lpAddend,1); } inline static long atomicdel(long* lpAddend){ + + /* #if (TARGET_OS == OS_WINDOWS) return InterlockedDecrement(lpAddend); #elif (TARGET_OS == OS_POSIX) return __sync_sub_and_fetch(lpAddend,1); #endif + */ + return ATOM_SUB(lpAddend,1); } inline static void atomicinit(long* lpAddend) { - *lpAddend = 0; + //*lpAddend = 0; + ATOM_INC(lpAddend); } inline static void atomicuninit(long* lpAddend) { - *lpAddend = 0; + //*lpAddend = 0; + ATOM_INC(lpAddend); } #endif \ No newline at end of file diff --git a/include/util/locksection.hpp b/include/util/locksection.hpp index fa4100bd7eb9d92668103b573aa42b904a41c6bc..7a7183c7f0cf10b95426160b2439e2e4ad7d6dae 100644 --- a/include/util/locksection.hpp +++ b/include/util/locksection.hpp @@ -14,11 +14,13 @@ #if (TARGET_OS == OS_WINDOWS) typedef int os_pid_t; typedef HANDLE os_thread_t; + typedef HANDLE os_pipe_t; typedef HANDLE os_sem_t; typedef CRITICAL_SECTION os_mutex_t; #elif (TARGET_OS == OS_POSIX) typedef pid_t os_pid_t; typedef pthread_t os_thread_t; + typedef int os_pipe_t; typedef sem_t os_sem_t; typedef pthread_mutex_t os_mutex_t; #endif @@ -273,7 +275,7 @@ public: T *t; }; -typedef CStackLockWrapper CStackAutoCSLock; +typedef CStackLockWrapper2 CStackAutoCSLock; #define DECLARE_AUTOLOCK_CS(name) CAutoCriticalSection m_cs ## name diff --git a/include/util/singletion.hpp b/include/util/singletion.hpp index deaa7e830f6eef7b4b767ebec965f200ecd2f5f7..f546b241f2ac0da7d896fae2429fc2308c940455 100644 --- a/include/util/singletion.hpp +++ b/include/util/singletion.hpp @@ -8,36 +8,38 @@ using namespace util; #ifdef __cplusplus - -//#include - template < class _Type > class CPP_NO_VTABLE CSingletion { public: static _Type* GetInstance() { + CStackAutoCSLock lock(s_mutex); + if (NULL == s_pInstance) { s_pInstance = new _Type; } - //s_ref.fetch_add(1, std::memory_order_release); - - atomicadd(&s_ref); - + else + { + s_ref = s_ref + 1; + } return s_pInstance; } static void DestroyInstance() { - //s_ref.fetch_sub(1, std::memory_order_release); - atomicdel(&s_ref); - //if (s_ref.load(std::memory_order_acquire) == 0) - if (!s_ref) + CStackAutoCSLock lock(s_mutex); + + if (s_ref == 1) { delete s_pInstance; s_pInstance = 0; } + else + { + s_ref--; + } } protected: @@ -49,16 +51,14 @@ protected: private: static _Type* s_pInstance; - //static std::atomic_long s_ref; static long s_ref; + static CAutoCriticalSection s_mutex; }; - ////////////////////////////////////////////////////////////////////////// -template T* CSingletion::s_pInstance = 0; -//template std::atomic_long CSingletion::s_ref(0); -template long CSingletion::s_ref = 0; +template T* CSingletion::s_pInstance = 0; +template long CSingletion::s_ref = 0; +template CAutoCriticalSection CSingletion::s_mutex; ////////////////////////////////////////////////////////////////////////// - #endif diff --git a/include/util/thread.hpp b/include/util/thread.hpp new file mode 100644 index 0000000000000000000000000000000000000000..65d7dbc78ec3bc5afcc9e86d4b15bdab2177c6dd --- /dev/null +++ b/include/util/thread.hpp @@ -0,0 +1,156 @@ +#ifndef _UTIL_THREAD_H_ +#define _UTIL_THREAD_H_ + +#include +#include + + +#if (TARGET_OS == OS_WINDOWS) + +#include + + +typedef void(*funcentry)(void* arg); + + +struct thread_ctx { + funcentry entry; + void* arg; + os_thread_t self; +}; + + + +static UINT __stdcall os_thread_start(void* arg) { + + funcentry func; + void* threadarg; + thread_ctx* ctx = NULL; + ctx = (thread_ctx*)(arg); + + func = ctx->entry; + threadarg = ctx->arg; + free(ctx); + + func(threadarg); + + return 0; +} + + +inline int os_thread_create(os_thread_t *tid, void (*entry)(void *arg), void *arg) { + struct thread_ctx* ctx; + int err; + HANDLE thread; + + ctx = (thread_ctx*)malloc(sizeof(thread_ctx)); + if (ctx == NULL) + return 0; + + ctx->entry = entry; + ctx->arg = arg; + + thread = (HANDLE)_beginthreadex(NULL, + 0, + os_thread_start, + ctx, + CREATE_SUSPENDED, + NULL); + if (thread == NULL) { + + free(ctx); + return 0; + } + else { + err = 0; + *tid = thread; + ctx->self = thread; + ResumeThread(thread); + } + return 1; +} + +inline int os_thread_join(os_thread_t *tid) { + if (WaitForSingleObject(*tid, INFINITE)) + return 1; + else { + CloseHandle(*tid); + *tid = 0; + return 0; + } +} + + +inline int os_thread_equal(const os_thread_t* t1, const os_thread_t* t2) { + return *t1 == *t2; +} + + +#elif (TARGET_OS == OS_POSIX) + +#include +#include +#include + +inline size_t thread_stack_size() { +#if defined(__APPLE__) || defined(__linux__) + struct rlimit lim; + + if (getrlimit(RLIMIT_STACK, &lim)) + abort(); + + if (lim.rlim_cur != RLIM_INFINITY) { + /* pthread_attr_setstacksize() expects page-aligned values. */ + lim.rlim_cur -= lim.rlim_cur % (rlim_t) getpagesize(); + if (lim.rlim_cur >= PTHREAD_STACK_MIN) + return lim.rlim_cur; + } +#endif + +#if !defined(__linux__) + return 0; +#elif defined(__PPC__) || defined(__ppc__) || defined(__powerpc__) + return 4 << 20; /* glibc default. */ +#else + return 2 << 20; /* glibc default. */ +#endif +} + + +inline int os_thread_create(os_thread_t *tid, void (*entry)(void *arg), void *arg) { + int err; + size_t stack_size; + pthread_attr_t* attr; + pthread_attr_t attr_storage; + + attr = NULL; + stack_size = thread_stack_size(); + + if (stack_size > 0) { + attr = &attr_storage; + + if (pthread_attr_init(attr)) + abort(); + + if (pthread_attr_setstacksize(attr, stack_size)) + abort(); + } + + err = pthread_create(tid, attr, (void*(*)(void*)) entry, arg); + + if (attr != NULL) + pthread_attr_destroy(attr); + +} + +inline int os_thread_join(os_thread_t *tid) { + return pthread_join(*tid, NULL); +} + +inline int os_thread_equal(const os_thread_t* t1, const os_thread_t* t2) { + return pthread_equal(*t1, *t2); +} + +#endif + +#endif \ No newline at end of file diff --git a/include/util/timesleep.hpp b/include/util/timesleep.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e3513e19359fd3a3e592710ebc25ebb2842a06b2 --- /dev/null +++ b/include/util/timesleep.hpp @@ -0,0 +1,13 @@ +#ifndef _UTIL_TIMESLEEP_H_ +#define _UTIL_TIMESLEEP_H_ + +#include + +#if (TARGET_OS == OS_WINDOWS) + #define TimeSleep(x) Sleep(x * 1000); + +#elif (TARGET_OS == OS_POSIX) + #define TimeSleep(x) sleep(x); +#endif + +#endif \ No newline at end of file diff --git a/include/util/util.h b/include/util/util.h index 4fb2cc25237b3deed1d399f1e8435c8496a0257c..e0828cd872794005fa9c61362e84d81e39ce715d 100644 --- a/include/util/util.h +++ b/include/util/util.h @@ -5,6 +5,8 @@ #include #include #include +#include + #include #include #include @@ -17,4 +19,11 @@ //debug #include +//time +#include + +//sprintf +#include + + #endif // !_UTIL_H_ \ No newline at end of file diff --git a/infoanalysis/infoanalysisimpl.cpp b/infoanalysis/infoanalysisimpl.cpp index 8dee7350694e53d0635ed0832b8e96d007289b56..c6a1f74baf7161b13a5de23682262dd16d625496 100644 --- a/infoanalysis/infoanalysisimpl.cpp +++ b/infoanalysis/infoanalysisimpl.cpp @@ -1,7 +1,7 @@ #include "infoanalysisimpl.h" #include "crootimpl.h" #include "json.h" -#include +#include CInfoAnalysisImpl::CInfoAnalysisImpl(void) { @@ -63,7 +63,7 @@ std_method_impl CInfoAnalysisImpl::NewLoadFileObject(const TCHAR* filepath, IBas if (m_pRot != INULL) { - m_pRot->GetObject(CLSID_IAsynIo, _uuidof(IAsynIo), (IBase**)&pAsynIo.m_p); + m_pRot->GetObject(CLSID_IAsynFrame, _uuidof(IAsynIo), (IBase**)&pAsynIo.m_p); } if (pAsynIo != NULL) @@ -78,12 +78,7 @@ std_method_impl CInfoAnalysisImpl::NewLoadFileObject(const TCHAR* filepath, IBas tstring asynio; asynio.append(path); -#ifdef _MSC_VER - asynio += _T("\\asynIo.dll"); -#elif __GNUC__ - asynio += _T("//libasynio.so"); -#endif // __GNUC__ - + asynio += ModNameToModPath(_T("asynio")); retrtpv(FileIsExist(asynio.c_str()), E_FAIL) @@ -93,7 +88,7 @@ std_method_impl CInfoAnalysisImpl::NewLoadFileObject(const TCHAR* filepath, IBas { return E_FAIL; } - hr = comLoader.CreateInstance(CLSID_IAsynIo, NULL, NULL, _uuidof(IAsynIo), (void**)&pAsynIo.m_p); + hr = comLoader.CreateInstance(CLSID_IAsynFrame, NULL, NULL, _uuidof(IAsynIo), (void**)&pAsynIo.m_p); if (hr == S_OK) { diff --git a/main/main.cpp b/main/main.cpp index f820344d7c814d8ec6f4ba84e1fdc1d07190701d..012e5e008e20dc8640e8ef038e0f5bd9628f6705 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -21,7 +21,6 @@ int WINAPI WinMain( HINSTANCE hInstance, stringconfig += _T("mainmoduleconfig.json"); stringcomenv += ModNameToModPath(_T("comenv")); - printf("11\n"); BOOL bRet = loader.LoadCom(stringcomenv.c_str()); if (bRet == TRUE) diff --git a/mainui.sln b/mainui.sln index 1a53ce588f754e58c393d162286ca9152017deba..df8ebb388c9e0d6ae34b9c3779bdf4d76d223e4b 100644 --- a/mainui.sln +++ b/mainui.sln @@ -17,6 +17,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "main", "main\mainui.vcxproj EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mempool", "mempool\mempool.vcxproj", "{4DADD130-5D03-4B60-8A45-9D6C725A6043}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "protocol", "protocol\protocol.vcxproj", "{1E152A99-DC53-4334-A44A-F623F5CB49C8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -67,6 +69,12 @@ Global {4DADD130-5D03-4B60-8A45-9D6C725A6043}.Release|Win32.ActiveCfg = Release|Win32 {4DADD130-5D03-4B60-8A45-9D6C725A6043}.Release|Win32.Build.0 = Release|Win32 {4DADD130-5D03-4B60-8A45-9D6C725A6043}.Release|x64.ActiveCfg = Release|Win32 + {1E152A99-DC53-4334-A44A-F623F5CB49C8}.Debug|Win32.ActiveCfg = Debug|Win32 + {1E152A99-DC53-4334-A44A-F623F5CB49C8}.Debug|Win32.Build.0 = Debug|Win32 + {1E152A99-DC53-4334-A44A-F623F5CB49C8}.Debug|x64.ActiveCfg = Debug|Win32 + {1E152A99-DC53-4334-A44A-F623F5CB49C8}.Release|Win32.ActiveCfg = Release|Win32 + {1E152A99-DC53-4334-A44A-F623F5CB49C8}.Release|Win32.Build.0 = Release|Win32 + {1E152A99-DC53-4334-A44A-F623F5CB49C8}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/plugin/CMakeLists.txt b/plugin/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..58e7419f4e05be27220b98fc7550bf74c620e748 --- /dev/null +++ b/plugin/CMakeLists.txt @@ -0,0 +1,44 @@ +cmake_minimum_required(VERSION 2.8) + +set(sshchannel_src dllmain.cpp + sshchannelimpl.cpp) + + +if (${UNIX_OS}) + include_directories( + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}//extensions/include + ${by3rd_library_include} + /usr/local/include + /opt/local/include + /usr/include + ) +elseif (${WIN_OS}) + +else() + +endif() + + +link_directories(/usr/lib/x86_64-linux-gnu) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) + +add_library(sshchannel SHARED ${sshchannel_src}) + +set_target_properties(sshchannel PROPERTIES OUTPUT_NAME "sshchannel") + +set_target_properties(sshchannel PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -std=c++11 -fpermissive -fPIC -frtti -fexceptions") + +if(CMAKE_BUILD_TYPE STREQUAL Debug) + set_target_properties(sshchannel PROPERTIES COMPILE_FLAGS "-g3") +endif() + +if(CMAKE_BUILD_TYPE STREQUAL Release) + set_target_properties(sshchannel PROPERTIES COMPILE_FLAGS "-O3") +endif() + + +install(TARGETS sshchannel + LIBRARY DESTINATION bin + ARCHIVE DESTINATION bin) diff --git a/plugin/dllmain.cpp b/plugin/dllmain.cpp index 117ddbc146aaf49e8a5992e319bf574324efd2b4..87cf3017d88dd819f1d7f720dd6ed5ce14dcb6f6 100644 --- a/plugin/dllmain.cpp +++ b/plugin/dllmain.cpp @@ -1,7 +1,5 @@ // dllmain.cpp : Defines the entry point for the DLL application. #include "stdafx.h" - - BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved @@ -17,12 +15,13 @@ BOOL APIENTRY DllMain( HMODULE hModule, } return TRUE; } + + BEGIN_CLIDMAP CLIDMAPENTRY_BEGIN - //CLIDMAPENTRY_PROGID(CLSID_IUibase, CUiBaseImpl, "UibaseImpl.impl") + CLIDMAPENTRY_END END_CLIDMAP_AND_EXPORTFUN - MD_EXPORTS DllCanUnloadNow(void) { return FALSE; diff --git a/plugin/mainview.cpp b/plugin/mainview.cpp deleted file mode 100644 index 09aeb60003fc42a3a9fea5f80db2607a05530f23..0000000000000000000000000000000000000000 --- a/plugin/mainview.cpp +++ /dev/null @@ -1,6 +0,0 @@ -// Maincom.cpp : Defines the exported functions for the DLL application. -// - -#include "stdafx.h" - - diff --git a/plugin/mainview.vcproj b/plugin/mainview.vcproj deleted file mode 100644 index 0498720257e2152fe317f3168eea08dbeca055fc..0000000000000000000000000000000000000000 --- a/plugin/mainview.vcproj +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/plugin/mainviewimpl.cpp b/plugin/mainviewimpl.cpp deleted file mode 100644 index fa479b7ea93cf79635e6b737c2db267dbb19fc87..0000000000000000000000000000000000000000 --- a/plugin/mainviewimpl.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include "stdafx.h" -#include "mainviewimpl.h" - - -mainviewimpl::mainviewimpl() -{ -} - - -mainviewimpl::~mainviewimpl() -{ -} - -////////////////////////////////////////////////////////////////////////// -DOCALLMETHODIMP mainviewimpl::init_class(IBase* prot, IBase* punkOuter) -{ - DOCALLRESULT hr = S_OK; - if (prot != NULL) - { - m_pRot = prot; - } - return hr; -} -DOCALLMETHODIMP mainviewimpl::Init(void*) -{ - DOCALLRESULT hr = S_OK; - - return hr; -} -DOCALLMETHODIMP mainviewimpl::Uninit() -{ - DOCALLRESULT hr = S_OK; - - return hr; -} -DOCALLMETHODIMP mainviewimpl::Start() -{ - DOCALLRESULT hr = S_OK; - - return hr; -} -DOCALLMETHODIMP mainviewimpl::Stop() -{ - DOCALLRESULT hr = S_OK; - - return hr; -} -////////////////////////////////////////////////////////////////////////// -DOCALLMETHODIMP mainviewimpl::InitParams(const wchar_t* directui, DWORD dwStyles, DWORD dwExStyles) -{ - DOCALLRESULT hr = S_OK; - - return hr; -} -DOCALLMETHODIMP_(void*) mainviewimpl::Create(void* hParentHwnd) -{ - return this; -} -DOCALLMETHODIMP mainviewimpl::Destroy() -{ - DOCALLRESULT hr = S_OK; - - return hr; -} -DOCALLMETHODIMP_(BOOL) mainviewimpl::Show(int nCmdShow) -{ - BOOL bret = TRUE; - return bret; -} -DOCALLMETHODIMP_(INT_PTR) mainviewimpl::DoModal(void* hParentHwnd) -{ - INT_PTR intPtr = 1; - return intPtr; -} -DOCALLMETHODIMP mainviewimpl::EndModal(INT_PTR nResult) -{ - DOCALLRESULT hr = S_OK; - - return hr; -} - -DOCALLMETHODIMP_(void*) mainviewimpl::GetView() -{ - return this; -} -DOCALLMETHODIMP mainviewimpl::InitMessageLoop(IPaintManagerUI* pPaintManager) -{ - DOCALLRESULT hr = S_OK; - - return hr; -} -DOCALLMETHODIMP mainviewimpl::UnInitMessageLoop() -{ - DOCALLRESULT hr = S_OK; - - return hr; -} - diff --git a/plugin/mainviewimpl.h b/plugin/mainviewimpl.h deleted file mode 100644 index ecd407e3ac9ef5b4fd0c2319244035d74e567770..0000000000000000000000000000000000000000 --- a/plugin/mainviewimpl.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _MAINVIEW_H_ -#define _MAINVIEW_H_ - -#pragma once - -#include - - -class mainviewimpl : public IView, - public IPlugin, - public IPluginRun, - public CUnknownImp -{ -public: - mainviewimpl(); - ~mainviewimpl(); - - UNKNOWN_IMP3_(IPlugin, IPluginRun, IView); - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - DOCALLMETHODIMP init_class(IBase* prot, IBase* punkOuter); - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - DOCALLMETHOD(Init)(void*); - DOCALLMETHOD(Uninit)(); - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - DOCALLMETHOD(Start)(); - DOCALLMETHOD(Stop)(); - ////////////////////////////////////////////////////////////////////////// - - ////////////////////////////////////////////////////////////////////////// - DOCALLMETHOD(InitParams)(const wchar_t* directui, DWORD dwStyles = 0, DWORD dwExStyles = 0); - DOCALLMETHOD_(void*, Create)(void* hParentHwnd = NULL); - DOCALLMETHOD(Destroy)(); - DOCALLMETHOD_(BOOL, Show)(int nCmdShow) = 0; - DOCALLMETHOD_(INT_PTR, DoModal)(void* hParentHwnd = NULL); - DOCALLMETHOD(EndModal)(INT_PTR nResult); - DOCALLMETHOD_(void*, GetView)(); - DOCALLMETHOD(InitMessageLoop)(IPaintManagerUI* pPaintManager); - DOCALLMETHOD(UnInitMessageLoop)(); -private: - _lComPtr m_pRot; - -}; -#endif - diff --git a/plugin/mainview.vcxproj b/plugin/protocol.vcxproj similarity index 91% rename from plugin/mainview.vcxproj rename to plugin/protocol.vcxproj index 6c48c3cf1d4e41d5a6f7631104407fefc9fb94f5..cab25d6fb131a06c1bbab10c48a97ff8c5577341 100644 --- a/plugin/mainview.vcxproj +++ b/plugin/protocol.vcxproj @@ -11,21 +11,21 @@ - {4DADD130-5D03-4B60-8A45-9D6C725A6043} + {1E152A99-DC53-4334-A44A-F623F5CB49C8} Plugin Win32Proj - 8.1 + 10.0.16299.0 DynamicLibrary - v140 + v141 Unicode true DynamicLibrary - v140 + v141 Unicode @@ -60,12 +60,12 @@ Disabled - ../include;%(AdditionalIncludeDirectories) + ../include;../extensions/include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_EXPORTS;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL - Use + NotUsing Level3 EditAndContinue @@ -84,11 +84,11 @@ MaxSpeed true - ../include;%(AdditionalIncludeDirectories) + ../include;../extensions/include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_EXPORTS;%(PreprocessorDefinitions) MultiThreadedDLL true - Use + NotUsing Level3 ProgramDatabase @@ -117,14 +117,12 @@ false - Create Create - diff --git a/plugin/stdafx.h b/plugin/stdafx.h index 9755f14dcdd651529c19221774488c10ed76f6ea..0f2c0d7f86b6e301819d097dff60d953c4c755cc 100644 --- a/plugin/stdafx.h +++ b/plugin/stdafx.h @@ -6,8 +6,15 @@ #ifndef _STDAFX_H_ #define _STDAFX_H_ -#define _OS_WINDOWSSYSTEM -#include +#include +#include +#include +#include +#include +using namespace by; + +#include +#include #endif \ No newline at end of file diff --git a/protocol/CMakeLists.txt b/protocol/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..638f38d92bf24bbacaa6cb02d09fd0802713e4ae --- /dev/null +++ b/protocol/CMakeLists.txt @@ -0,0 +1,46 @@ +cmake_minimum_required(VERSION 2.8) + +set(protocol_src dllmain.cpp + httpcreatorimpl.cpp + http_parser.cpp + httpimpl.cpp) + + +if (${UNIX_OS}) + include_directories( + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}//extensions/include + ${by3rd_library_include} + /usr/local/include + /opt/local/include + /usr/include + ) +elseif (${WIN_OS}) + +else() + +endif() + + +link_directories(/usr/lib/x86_64-linux-gnu) + +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) + +add_library(protocol SHARED ${protocol_src}) + +set_target_properties(protocol PROPERTIES OUTPUT_NAME "protocol") + +set_target_properties(protocol PROPERTIES COMPILE_FLAGS "-fvisibility=hidden -std=c++11 -fpermissive -fPIC -frtti -fexceptions") + +if(CMAKE_BUILD_TYPE STREQUAL Debug) + set_target_properties(protocol PROPERTIES COMPILE_FLAGS "-g3") +endif() + +if(CMAKE_BUILD_TYPE STREQUAL Release) + set_target_properties(protocol PROPERTIES COMPILE_FLAGS "-O3") +endif() + + +install(TARGETS protocol + LIBRARY DESTINATION bin + ARCHIVE DESTINATION bin) diff --git a/protocol/ReadMe.txt b/protocol/ReadMe.txt new file mode 100644 index 0000000000000000000000000000000000000000..902220d6f01da3309339d7ae9c955f9b811fc051 --- /dev/null +++ b/protocol/ReadMe.txt @@ -0,0 +1,41 @@ +======================================================================== + DYNAMIC LINK LIBRARY : Plugin Project Overview +======================================================================== + +AppWizard has created this Plugin DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your Plugin application. + + +Plugin.vcproj + This is the main project file for VC++ projects generated using an Application Wizard. + It contains information about the version of Visual C++ that generated the file, and + information about the platforms, configurations, and project features selected with the + Application Wizard. + +Plugin.cpp + This is the main DLL source file. + + When created, this DLL does not export any symbols. As a result, it + will not produce a .lib file when it is built. If you wish this project + to be a project dependency of some other project, you will either need to + add code to export some symbols from the DLL so that an export library + will be produced, or you can set the Ignore Input Library property to Yes + on the General propert page of the Linker folder in the project's Property + Pages dialog box. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named Plugin.pch and a precompiled types file named StdAfx.obj. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" comments to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/protocol/dllexports.def b/protocol/dllexports.def new file mode 100644 index 0000000000000000000000000000000000000000..e0a4276e2262900ca133a8f025a08a1aa28d91e9 --- /dev/null +++ b/protocol/dllexports.def @@ -0,0 +1,5 @@ +EXPORTS + DllCanUnloadNow PRIVATE + DllGetClassObject PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE \ No newline at end of file diff --git a/protocol/dllmain.cpp b/protocol/dllmain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e72d1200460d84a7b452219597fab15a9cf197c --- /dev/null +++ b/protocol/dllmain.cpp @@ -0,0 +1,39 @@ +// dllmain.cpp : Defines the entry point for the DLL application. +#include "stdafx.h" +#include "httpcreatorimpl.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + + +BEGIN_CLIDMAP + CLIDMAPENTRY_BEGIN + CLIDMAPENTRY_PROGID(CLSID_IHttp, CHttpCreatorImpl, "HttpCreatorImpl.Impl") + CLIDMAPENTRY_END +END_CLIDMAP_AND_EXPORTFUN +MD_EXPORTS DllCanUnloadNow(void) +{ + return FALSE; +} + +MD_EXPORTS DllRegisterServer(void) +{ + return S_OK; +} +MD_EXPORTS DllUnregisterServer(void) +{ + return S_OK; +} \ No newline at end of file diff --git a/protocol/http_parser.cpp b/protocol/http_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b5657b02c52c4d724908f92401e3302702443a4 --- /dev/null +++ b/protocol/http_parser.cpp @@ -0,0 +1,2423 @@ +/* Copyright Joyent, Inc. and other Node contributors. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#include "http_parser.h" +#include +#include +#include +#include +#include + +#ifndef ULLONG_MAX +# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */ +#endif + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#endif + +#ifndef BIT_AT +# define BIT_AT(a, i) \ + (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \ + (1 << ((unsigned int) (i) & 7)))) +#endif + +#ifndef ELEM_AT +# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v)) +#endif + +#define SET_ERRNO(e) \ +do { \ + parser->http_errno = (e); \ +} while(0) + +#define CURRENT_STATE() p_state +#define UPDATE_STATE(V) p_state = (enum state) (V); +#define RETURN(V) \ +do { \ + parser->state = CURRENT_STATE(); \ + return (V); \ +} while (0); +#define REEXECUTE() \ + goto reexecute; \ + + +#ifdef __GNUC__ +# define LIKELY(X) __builtin_expect(!!(X), 1) +# define UNLIKELY(X) __builtin_expect(!!(X), 0) +#else +# define LIKELY(X) (X) +# define UNLIKELY(X) (X) +#endif + + +/* Run the notify callback FOR, returning ER if it fails */ +#define CALLBACK_NOTIFY_(FOR, ER) \ +do { \ + assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ + \ + if (LIKELY(settings->on_##FOR)) { \ + parser->state = CURRENT_STATE(); \ + if (UNLIKELY(0 != settings->on_##FOR(parser))) { \ + SET_ERRNO(HPE_CB_##FOR); \ + } \ + UPDATE_STATE(parser->state); \ + \ + /* We either errored above or got paused; get out */ \ + if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ + return (ER); \ + } \ + } \ +} while (0) + +/* Run the notify callback FOR and consume the current byte */ +#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1) + +/* Run the notify callback FOR and don't consume the current byte */ +#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data) + +/* Run data callback FOR with LEN bytes, returning ER if it fails */ +#define CALLBACK_DATA_(FOR, LEN, ER) \ +do { \ + assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \ + \ + if (FOR##_mark) { \ + if (LIKELY(settings->on_##FOR)) { \ + parser->state = CURRENT_STATE(); \ + if (UNLIKELY(0 != \ + settings->on_##FOR(parser, FOR##_mark, (LEN)))) { \ + SET_ERRNO(HPE_CB_##FOR); \ + } \ + UPDATE_STATE(parser->state); \ + \ + /* We either errored above or got paused; get out */ \ + if (UNLIKELY(HTTP_PARSER_ERRNO(parser) != HPE_OK)) { \ + return (ER); \ + } \ + } \ + FOR##_mark = NULL; \ + } \ +} while (0) + +/* Run the data callback FOR and consume the current byte */ +#define CALLBACK_DATA(FOR) \ + CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1) + +/* Run the data callback FOR and don't consume the current byte */ +#define CALLBACK_DATA_NOADVANCE(FOR) \ + CALLBACK_DATA_(FOR, p - FOR##_mark, p - data) + +/* Set the mark FOR; non-destructive if mark is already set */ +#define MARK(FOR) \ +do { \ + if (!FOR##_mark) { \ + FOR##_mark = p; \ + } \ +} while (0) + +/* Don't allow the total size of the HTTP headers (including the status + * line) to exceed HTTP_MAX_HEADER_SIZE. This check is here to protect + * embedders against denial-of-service attacks where the attacker feeds + * us a never-ending header that the embedder keeps buffering. + * + * This check is arguably the responsibility of embedders but we're doing + * it on the embedder's behalf because most won't bother and this way we + * make the web a little safer. HTTP_MAX_HEADER_SIZE is still far bigger + * than any reasonable request or response so this should never affect + * day-to-day operation. + */ +#define COUNT_HEADER_SIZE(V) \ +do { \ + parser->nread += (V); \ + if (UNLIKELY(parser->nread > (HTTP_MAX_HEADER_SIZE))) { \ + SET_ERRNO(HPE_HEADER_OVERFLOW); \ + goto error; \ + } \ +} while (0) + + +#define PROXY_CONNECTION "proxy-connection" +#define CONNECTION "connection" +#define CONTENT_LENGTH "content-length" +#define TRANSFER_ENCODING "transfer-encoding" +#define UPGRADE "upgrade" +#define CHUNKED "chunked" +#define KEEP_ALIVE "keep-alive" +#define CLOSE "close" + + +static const char *method_strings[] = + { +#define XX(num, name, string) #string, + HTTP_METHOD_MAP(XX) +#undef XX + }; + + +/* Tokens as defined by rfc 2616. Also lowercases them. + * token = 1* + * separators = "(" | ")" | "<" | ">" | "@" + * | "," | ";" | ":" | "\" | <"> + * | "/" | "[" | "]" | "?" | "=" + * | "{" | "}" | SP | HT + */ +static const char tokens[256] = { +/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ + 0, 0, 0, 0, 0, 0, 0, 0, +/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ + 0, '!', 0, '#', '$', '%', '&', '\'', +/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ + 0, 0, '*', '+', 0, '-', '.', 0, +/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ + '0', '1', '2', '3', '4', '5', '6', '7', +/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ + '8', '9', 0, 0, 0, 0, 0, 0, +/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ + 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', +/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', +/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ + 'x', 'y', 'z', 0, 0, 0, '^', '_', +/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', +/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', +/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', +/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ + 'x', 'y', 'z', 0, '|', 0, '~', 0 }; + + +static const int8_t unhex[256] = + {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1 + ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1 + ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 + }; + + +#if HTTP_PARSER_STRICT +# define T(v) 0 +#else +# define T(v) v +#endif + + +static const uint8_t normal_url_char[32] = { +/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */ + 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0, +/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ + 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0, +/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ + 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128, +/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, +/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128, +/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ + 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, }; + +#undef T + +enum state + { s_dead = 1 /* important that this is > 0 */ + + , s_start_req_or_res + , s_res_or_resp_H + , s_start_res + , s_res_H + , s_res_HT + , s_res_HTT + , s_res_HTTP + , s_res_http_major + , s_res_http_dot + , s_res_http_minor + , s_res_http_end + , s_res_first_status_code + , s_res_status_code + , s_res_status_start + , s_res_status + , s_res_line_almost_done + + , s_start_req + + , s_req_method + , s_req_spaces_before_url + , s_req_schema + , s_req_schema_slash + , s_req_schema_slash_slash + , s_req_server_start + , s_req_server + , s_req_server_with_at + , s_req_path + , s_req_query_string_start + , s_req_query_string + , s_req_fragment_start + , s_req_fragment + , s_req_http_start + , s_req_http_H + , s_req_http_HT + , s_req_http_HTT + , s_req_http_HTTP + , s_req_http_major + , s_req_http_dot + , s_req_http_minor + , s_req_http_end + , s_req_line_almost_done + + , s_header_field_start + , s_header_field + , s_header_value_discard_ws + , s_header_value_discard_ws_almost_done + , s_header_value_discard_lws + , s_header_value_start + , s_header_value + , s_header_value_lws + + , s_header_almost_done + + , s_chunk_size_start + , s_chunk_size + , s_chunk_parameters + , s_chunk_size_almost_done + + , s_headers_almost_done + , s_headers_done + + /* Important: 's_headers_done' must be the last 'header' state. All + * states beyond this must be 'body' states. It is used for overflow + * checking. See the PARSING_HEADER() macro. + */ + + , s_chunk_data + , s_chunk_data_almost_done + , s_chunk_data_done + + , s_body_identity + , s_body_identity_eof + + , s_message_done + }; + + +#define PARSING_HEADER(state) (state <= s_headers_done) + + +enum header_states + { h_general = 0 + , h_C + , h_CO + , h_CON + + , h_matching_connection + , h_matching_proxy_connection + , h_matching_content_length + , h_matching_transfer_encoding + , h_matching_upgrade + + , h_connection + , h_content_length + , h_transfer_encoding + , h_upgrade + + , h_matching_transfer_encoding_chunked + , h_matching_connection_token_start + , h_matching_connection_keep_alive + , h_matching_connection_close + , h_matching_connection_upgrade + , h_matching_connection_token + + , h_transfer_encoding_chunked + , h_connection_keep_alive + , h_connection_close + , h_connection_upgrade + }; + +enum http_host_state + { + s_http_host_dead = 1 + , s_http_userinfo_start + , s_http_userinfo + , s_http_host_start + , s_http_host_v6_start + , s_http_host + , s_http_host_v6 + , s_http_host_v6_end + , s_http_host_v6_zone_start + , s_http_host_v6_zone + , s_http_host_port_start + , s_http_host_port +}; + +/* Macros for character classes; depends on strict-mode */ +#define CR '\r' +#define LF '\n' +#define LOWER(c) (unsigned char)(c | 0x20) +#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') +#define IS_NUM(c) ((c) >= '0' && (c) <= '9') +#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) +#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f')) +#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \ + (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \ + (c) == ')') +#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \ + (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \ + (c) == '$' || (c) == ',') + +#define STRICT_TOKEN(c) (tokens[(unsigned char)c]) + +#if HTTP_PARSER_STRICT +#define TOKEN(c) (tokens[(unsigned char)c]) +#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c)) +#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') +#else +#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) +#define IS_URL_CHAR(c) \ + (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80)) +#define IS_HOST_CHAR(c) \ + (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_') +#endif + +/** + * Verify that a char is a valid visible (printable) US-ASCII + * character or %x80-FF + **/ +#define IS_HEADER_CHAR(ch) \ + (ch == CR || ch == LF || ch == 9 || ((unsigned char)ch > 31 && ch != 127)) + +#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res) + + +#if HTTP_PARSER_STRICT +# define STRICT_CHECK(cond) \ +do { \ + if (cond) { \ + SET_ERRNO(HPE_STRICT); \ + goto error; \ + } \ +} while (0) +# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead) +#else +# define STRICT_CHECK(cond) +# define NEW_MESSAGE() start_state +#endif + + +/* Map errno values to strings for human-readable output */ +#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s }, +static struct { + const char *name; + const char *description; +} http_strerror_tab[] = { + HTTP_ERRNO_MAP(HTTP_STRERROR_GEN) +}; +#undef HTTP_STRERROR_GEN + +int http_message_needs_eof(const http_parser *parser); + +/* Our URL parser. + * + * This is designed to be shared by http_parser_execute() for URL validation, + * hence it has a state transition + byte-for-byte interface. In addition, it + * is meant to be embedded in http_parser_parse_url(), which does the dirty + * work of turning state transitions URL components for its API. + * + * This function should only be invoked with non-space characters. It is + * assumed that the caller cares about (and can detect) the transition between + * URL and non-URL states by looking for these. + */ +static enum state +parse_url_char(enum state s, const char ch) +{ + if (ch == ' ' || ch == '\r' || ch == '\n') { + return s_dead; + } + +#if HTTP_PARSER_STRICT + if (ch == '\t' || ch == '\f') { + return s_dead; + } +#endif + + switch (s) { + case s_req_spaces_before_url: + /* Proxied requests are followed by scheme of an absolute URI (alpha). + * All methods except CONNECT are followed by '/' or '*'. + */ + + if (ch == '/' || ch == '*') { + return s_req_path; + } + + if (IS_ALPHA(ch)) { + return s_req_schema; + } + + break; + + case s_req_schema: + if (IS_ALPHA(ch)) { + return s; + } + + if (ch == ':') { + return s_req_schema_slash; + } + + break; + + case s_req_schema_slash: + if (ch == '/') { + return s_req_schema_slash_slash; + } + + break; + + case s_req_schema_slash_slash: + if (ch == '/') { + return s_req_server_start; + } + + break; + + case s_req_server_with_at: + if (ch == '@') { + return s_dead; + } + + /* FALLTHROUGH */ + case s_req_server_start: + case s_req_server: + if (ch == '/') { + return s_req_path; + } + + if (ch == '?') { + return s_req_query_string_start; + } + + if (ch == '@') { + return s_req_server_with_at; + } + + if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') { + return s_req_server; + } + + break; + + case s_req_path: + if (IS_URL_CHAR(ch)) { + return s; + } + + switch (ch) { + case '?': + return s_req_query_string_start; + + case '#': + return s_req_fragment_start; + } + + break; + + case s_req_query_string_start: + case s_req_query_string: + if (IS_URL_CHAR(ch)) { + return s_req_query_string; + } + + switch (ch) { + case '?': + /* allow extra '?' in query string */ + return s_req_query_string; + + case '#': + return s_req_fragment_start; + } + + break; + + case s_req_fragment_start: + if (IS_URL_CHAR(ch)) { + return s_req_fragment; + } + + switch (ch) { + case '?': + return s_req_fragment; + + case '#': + return s; + } + + break; + + case s_req_fragment: + if (IS_URL_CHAR(ch)) { + return s; + } + + switch (ch) { + case '?': + case '#': + return s; + } + + break; + + default: + break; + } + + /* We should never fall out of the switch above unless there's an error */ + return s_dead; +} + +size_t http_parser_execute (http_parser *parser, + const http_parser_settings *settings, + const char *data, + size_t len) +{ + char c, ch; + int8_t unhex_val; + const char *p = data; + const char *header_field_mark = 0; + const char *header_value_mark = 0; + const char *url_mark = 0; + const char *body_mark = 0; + const char *status_mark = 0; + enum state p_state = (enum state) parser->state; + const unsigned int lenient = parser->lenient_http_headers; + + /* We're in an error state. Don't bother doing anything. */ + if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { + return 0; + } + + if (len == 0) { + switch (CURRENT_STATE()) { + case s_body_identity_eof: + /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if + * we got paused. + */ + CALLBACK_NOTIFY_NOADVANCE(message_complete); + return 0; + + case s_dead: + case s_start_req_or_res: + case s_start_res: + case s_start_req: + return 0; + + default: + SET_ERRNO(HPE_INVALID_EOF_STATE); + return 1; + } + } + + + if (CURRENT_STATE() == s_header_field) + header_field_mark = data; + if (CURRENT_STATE() == s_header_value) + header_value_mark = data; + switch (CURRENT_STATE()) { + case s_req_path: + case s_req_schema: + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + case s_req_server: + case s_req_server_with_at: + case s_req_query_string_start: + case s_req_query_string: + case s_req_fragment_start: + case s_req_fragment: + url_mark = data; + break; + case s_res_status: + status_mark = data; + break; + default: + break; + } + + for (p=data; p != data + len; p++) { + ch = *p; + + if (PARSING_HEADER(CURRENT_STATE())) + COUNT_HEADER_SIZE(1); + +reexecute: + switch (CURRENT_STATE()) { + + case s_dead: + /* this state is used after a 'Connection: close' message + * the parser will error out if it reads another message + */ + if (LIKELY(ch == CR || ch == LF)) + break; + + SET_ERRNO(HPE_CLOSED_CONNECTION); + goto error; + + case s_start_req_or_res: + { + if (ch == CR || ch == LF) + break; + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + if (ch == 'H') { + UPDATE_STATE(s_res_or_resp_H); + + CALLBACK_NOTIFY(message_begin); + } else { + parser->type = HTTP_REQUEST; + UPDATE_STATE(s_start_req); + REEXECUTE(); + } + + break; + } + + case s_res_or_resp_H: + if (ch == 'T') { + parser->type = HTTP_RESPONSE; + UPDATE_STATE(s_res_HT); + } else { + if (UNLIKELY(ch != 'E')) { + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + + parser->type = HTTP_REQUEST; + parser->method = HTTP_HEAD; + parser->index = 2; + UPDATE_STATE(s_req_method); + } + break; + + case s_start_res: + { + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + switch (ch) { + case 'H': + UPDATE_STATE(s_res_H); + break; + + case CR: + case LF: + break; + + default: + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + + CALLBACK_NOTIFY(message_begin); + break; + } + + case s_res_H: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_res_HT); + break; + + case s_res_HT: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_res_HTT); + break; + + case s_res_HTT: + STRICT_CHECK(ch != 'P'); + UPDATE_STATE(s_res_HTTP); + break; + + case s_res_HTTP: + STRICT_CHECK(ch != '/'); + UPDATE_STATE(s_res_http_major); + break; + + case s_res_http_major: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_major = ch - '0'; + UPDATE_STATE(s_res_http_dot); + break; + + case s_res_http_dot: + { + if (UNLIKELY(ch != '.')) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + UPDATE_STATE(s_res_http_minor); + break; + } + + case s_res_http_minor: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_minor = ch - '0'; + UPDATE_STATE(s_res_http_end); + break; + + case s_res_http_end: + { + if (UNLIKELY(ch != ' ')) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + UPDATE_STATE(s_res_first_status_code); + break; + } + + case s_res_first_status_code: + { + if (!IS_NUM(ch)) { + if (ch == ' ') { + break; + } + + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + parser->status_code = ch - '0'; + UPDATE_STATE(s_res_status_code); + break; + } + + case s_res_status_code: + { + if (!IS_NUM(ch)) { + switch (ch) { + case ' ': + UPDATE_STATE(s_res_status_start); + break; + case CR: + case LF: + UPDATE_STATE(s_res_status_start); + REEXECUTE(); + break; + default: + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + break; + } + + parser->status_code *= 10; + parser->status_code += ch - '0'; + + if (UNLIKELY(parser->status_code > 999)) { + SET_ERRNO(HPE_INVALID_STATUS); + goto error; + } + + break; + } + + case s_res_status_start: + { + MARK(status); + UPDATE_STATE(s_res_status); + parser->index = 0; + + if (ch == CR || ch == LF) + REEXECUTE(); + + break; + } + + case s_res_status: + if (ch == CR) { + UPDATE_STATE(s_res_line_almost_done); + CALLBACK_DATA(status); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_field_start); + CALLBACK_DATA(status); + break; + } + + break; + + case s_res_line_almost_done: + STRICT_CHECK(ch != LF); + UPDATE_STATE(s_header_field_start); + break; + + case s_start_req: + { + if (ch == CR || ch == LF) + break; + parser->flags = 0; + parser->content_length = ULLONG_MAX; + + if (UNLIKELY(!IS_ALPHA(ch))) { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + parser->method = (enum http_method) 0; + parser->index = 1; + switch (ch) { + case 'A': parser->method = HTTP_ACL; break; + case 'B': parser->method = HTTP_BIND; break; + case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break; + case 'D': parser->method = HTTP_DELETE; break; + case 'G': parser->method = HTTP_GET; break; + case 'H': parser->method = HTTP_HEAD; break; + case 'L': parser->method = HTTP_LOCK; /* or LINK */ break; + case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH, MKCALENDAR */ break; + case 'N': parser->method = HTTP_NOTIFY; break; + case 'O': parser->method = HTTP_OPTIONS; break; + case 'P': parser->method = HTTP_POST; + /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */ + break; + case 'R': parser->method = HTTP_REPORT; /* or REBIND */ break; + case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH, SOURCE */ break; + case 'T': parser->method = HTTP_TRACE; break; + case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE, UNBIND, UNLINK */ break; + default: + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + UPDATE_STATE(s_req_method); + + CALLBACK_NOTIFY(message_begin); + + break; + } + + case s_req_method: + { + const char *matcher; + if (UNLIKELY(ch == '\0')) { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + matcher = method_strings[parser->method]; + if (ch == ' ' && matcher[parser->index] == '\0') { + UPDATE_STATE(s_req_spaces_before_url); + } else if (ch == matcher[parser->index]) { + ; /* nada */ + } else if ((ch >= 'A' && ch <= 'Z') || ch == '-') { + + switch (parser->method << 16 | parser->index << 8 | ch) { +#define XX(meth, pos, ch, new_meth) \ + case (HTTP_##meth << 16 | pos << 8 | ch): \ + parser->method = HTTP_##new_meth; break; + + XX(POST, 1, 'U', PUT) + XX(POST, 1, 'A', PATCH) + XX(POST, 1, 'R', PROPFIND) + XX(PUT, 2, 'R', PURGE) + XX(CONNECT, 1, 'H', CHECKOUT) + XX(CONNECT, 2, 'P', COPY) + XX(MKCOL, 1, 'O', MOVE) + XX(MKCOL, 1, 'E', MERGE) + XX(MKCOL, 1, '-', MSEARCH) + XX(MKCOL, 2, 'A', MKACTIVITY) + XX(MKCOL, 3, 'A', MKCALENDAR) + XX(SUBSCRIBE, 1, 'E', SEARCH) + XX(SUBSCRIBE, 1, 'O', SOURCE) + XX(REPORT, 2, 'B', REBIND) + XX(PROPFIND, 4, 'P', PROPPATCH) + XX(LOCK, 1, 'I', LINK) + XX(UNLOCK, 2, 'S', UNSUBSCRIBE) + XX(UNLOCK, 2, 'B', UNBIND) + XX(UNLOCK, 3, 'I', UNLINK) +#undef XX + default: + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + } else { + SET_ERRNO(HPE_INVALID_METHOD); + goto error; + } + + ++parser->index; + break; + } + + case s_req_spaces_before_url: + { + if (ch == ' ') break; + + MARK(url); + if (parser->method == HTTP_CONNECT) { + UPDATE_STATE(s_req_server_start); + } + + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + + break; + } + + case s_req_schema: + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + { + switch (ch) { + /* No whitespace allowed here */ + case ' ': + case CR: + case LF: + SET_ERRNO(HPE_INVALID_URL); + goto error; + default: + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + } + + break; + } + + case s_req_server: + case s_req_server_with_at: + case s_req_path: + case s_req_query_string_start: + case s_req_query_string: + case s_req_fragment_start: + case s_req_fragment: + { + switch (ch) { + case ' ': + UPDATE_STATE(s_req_http_start); + CALLBACK_DATA(url); + break; + case CR: + case LF: + parser->http_major = 0; + parser->http_minor = 9; + UPDATE_STATE((ch == CR) ? + s_req_line_almost_done : + s_header_field_start); + CALLBACK_DATA(url); + break; + default: + UPDATE_STATE(parse_url_char(CURRENT_STATE(), ch)); + if (UNLIKELY(CURRENT_STATE() == s_dead)) { + SET_ERRNO(HPE_INVALID_URL); + goto error; + } + } + break; + } + + case s_req_http_start: + switch (ch) { + case 'H': + UPDATE_STATE(s_req_http_H); + break; + case ' ': + break; + default: + SET_ERRNO(HPE_INVALID_CONSTANT); + goto error; + } + break; + + case s_req_http_H: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_req_http_HT); + break; + + case s_req_http_HT: + STRICT_CHECK(ch != 'T'); + UPDATE_STATE(s_req_http_HTT); + break; + + case s_req_http_HTT: + STRICT_CHECK(ch != 'P'); + UPDATE_STATE(s_req_http_HTTP); + break; + + case s_req_http_HTTP: + STRICT_CHECK(ch != '/'); + UPDATE_STATE(s_req_http_major); + break; + + case s_req_http_major: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_major = ch - '0'; + UPDATE_STATE(s_req_http_dot); + break; + + case s_req_http_dot: + { + if (UNLIKELY(ch != '.')) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + UPDATE_STATE(s_req_http_minor); + break; + } + + case s_req_http_minor: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + } + + parser->http_minor = ch - '0'; + UPDATE_STATE(s_req_http_end); + break; + + case s_req_http_end: + { + if (ch == CR) { + UPDATE_STATE(s_req_line_almost_done); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_field_start); + break; + } + + SET_ERRNO(HPE_INVALID_VERSION); + goto error; + break; + } + + /* end of request line */ + case s_req_line_almost_done: + { + if (UNLIKELY(ch != LF)) { + SET_ERRNO(HPE_LF_EXPECTED); + goto error; + } + + UPDATE_STATE(s_header_field_start); + break; + } + + case s_header_field_start: + { + if (ch == CR) { + UPDATE_STATE(s_headers_almost_done); + break; + } + + if (ch == LF) { + /* they might be just sending \n instead of \r\n so this would be + * the second \n to denote the end of headers*/ + UPDATE_STATE(s_headers_almost_done); + REEXECUTE(); + } + + c = TOKEN(ch); + + if (UNLIKELY(!c)) { + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + MARK(header_field); + + parser->index = 0; + UPDATE_STATE(s_header_field); + + switch (c) { + case 'c': + parser->header_state = h_C; + break; + + case 'p': + parser->header_state = h_matching_proxy_connection; + break; + + case 't': + parser->header_state = h_matching_transfer_encoding; + break; + + case 'u': + parser->header_state = h_matching_upgrade; + break; + + default: + parser->header_state = h_general; + break; + } + break; + } + + case s_header_field: + { + const char* start = p; + for (; p != data + len; p++) { + ch = *p; + c = TOKEN(ch); + + if (!c) + break; + + switch (parser->header_state) { + case h_general: + break; + + case h_C: + parser->index++; + parser->header_state = (c == 'o' ? h_CO : h_general); + break; + + case h_CO: + parser->index++; + parser->header_state = (c == 'n' ? h_CON : h_general); + break; + + case h_CON: + parser->index++; + switch (c) { + case 'n': + parser->header_state = h_matching_connection; + break; + case 't': + parser->header_state = h_matching_content_length; + break; + default: + parser->header_state = h_general; + break; + } + break; + + /* connection */ + + case h_matching_connection: + parser->index++; + if (parser->index > sizeof(CONNECTION)-1 + || c != CONNECTION[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CONNECTION)-2) { + parser->header_state = h_connection; + } + break; + + /* proxy-connection */ + + case h_matching_proxy_connection: + parser->index++; + if (parser->index > sizeof(PROXY_CONNECTION)-1 + || c != PROXY_CONNECTION[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(PROXY_CONNECTION)-2) { + parser->header_state = h_connection; + } + break; + + /* content-length */ + + case h_matching_content_length: + parser->index++; + if (parser->index > sizeof(CONTENT_LENGTH)-1 + || c != CONTENT_LENGTH[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(CONTENT_LENGTH)-2) { + parser->header_state = h_content_length; + } + break; + + /* transfer-encoding */ + + case h_matching_transfer_encoding: + parser->index++; + if (parser->index > sizeof(TRANSFER_ENCODING)-1 + || c != TRANSFER_ENCODING[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) { + parser->header_state = h_transfer_encoding; + } + break; + + /* upgrade */ + + case h_matching_upgrade: + parser->index++; + if (parser->index > sizeof(UPGRADE)-1 + || c != UPGRADE[parser->index]) { + parser->header_state = h_general; + } else if (parser->index == sizeof(UPGRADE)-2) { + parser->header_state = h_upgrade; + } + break; + + case h_connection: + case h_content_length: + case h_transfer_encoding: + case h_upgrade: + if (ch != ' ') parser->header_state = h_general; + break; + + default: + assert(0 && "Unknown header_state"); + break; + } + } + + COUNT_HEADER_SIZE(p - start); + + if (p == data + len) { + --p; + break; + } + + if (ch == ':') { + UPDATE_STATE(s_header_value_discard_ws); + CALLBACK_DATA(header_field); + break; + } + + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + case s_header_value_discard_ws: + if (ch == ' ' || ch == '\t') break; + + if (ch == CR) { + UPDATE_STATE(s_header_value_discard_ws_almost_done); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_value_discard_lws); + break; + } + + /* FALLTHROUGH */ + + case s_header_value_start: + { + MARK(header_value); + + UPDATE_STATE(s_header_value); + parser->index = 0; + + c = LOWER(ch); + + switch (parser->header_state) { + case h_upgrade: + parser->flags |= F_UPGRADE; + parser->header_state = h_general; + break; + + case h_transfer_encoding: + /* looking for 'Transfer-Encoding: chunked' */ + if ('c' == c) { + parser->header_state = h_matching_transfer_encoding_chunked; + } else { + parser->header_state = h_general; + } + break; + + case h_content_length: + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + } + + if (parser->flags & F_CONTENTLENGTH) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } + + parser->flags |= F_CONTENTLENGTH; + parser->content_length = ch - '0'; + break; + + case h_connection: + /* looking for 'Connection: keep-alive' */ + if (c == 'k') { + parser->header_state = h_matching_connection_keep_alive; + /* looking for 'Connection: close' */ + } else if (c == 'c') { + parser->header_state = h_matching_connection_close; + } else if (c == 'u') { + parser->header_state = h_matching_connection_upgrade; + } else { + parser->header_state = h_matching_connection_token; + } + break; + + /* Multi-value `Connection` header */ + case h_matching_connection_token_start: + break; + + default: + parser->header_state = h_general; + break; + } + break; + } + + case s_header_value: + { + const char* start = p; + enum header_states h_state = (enum header_states) parser->header_state; + for (; p != data + len; p++) { + ch = *p; + if (ch == CR) { + UPDATE_STATE(s_header_almost_done); + parser->header_state = h_state; + CALLBACK_DATA(header_value); + break; + } + + if (ch == LF) { + UPDATE_STATE(s_header_almost_done); + COUNT_HEADER_SIZE(p - start); + parser->header_state = h_state; + CALLBACK_DATA_NOADVANCE(header_value); + REEXECUTE(); + } + + if (!lenient && !IS_HEADER_CHAR(ch)) { + SET_ERRNO(HPE_INVALID_HEADER_TOKEN); + goto error; + } + + c = LOWER(ch); + + switch (h_state) { + case h_general: + { + const char* p_cr; + const char* p_lf; + size_t limit = data + len - p; + + limit = MIN(limit, HTTP_MAX_HEADER_SIZE); + + p_cr = (const char*) memchr(p, CR, limit); + p_lf = (const char*) memchr(p, LF, limit); + if (p_cr != NULL) { + if (p_lf != NULL && p_cr >= p_lf) + p = p_lf; + else + p = p_cr; + } else if (UNLIKELY(p_lf != NULL)) { + p = p_lf; + } else { + p = data + len; + } + --p; + + break; + } + + case h_connection: + case h_transfer_encoding: + assert(0 && "Shouldn't get here."); + break; + + case h_content_length: + { + uint64_t t; + + if (ch == ' ') break; + + if (UNLIKELY(!IS_NUM(ch))) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + parser->header_state = h_state; + goto error; + } + + t = parser->content_length; + t *= 10; + t += ch - '0'; + + /* Overflow? Test against a conservative limit for simplicity. */ + if (UNLIKELY((ULLONG_MAX - 10) / 10 < parser->content_length)) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + parser->header_state = h_state; + goto error; + } + + parser->content_length = t; + break; + } + + /* Transfer-Encoding: chunked */ + case h_matching_transfer_encoding_chunked: + parser->index++; + if (parser->index > sizeof(CHUNKED)-1 + || c != CHUNKED[parser->index]) { + h_state = h_general; + } else if (parser->index == sizeof(CHUNKED)-2) { + h_state = h_transfer_encoding_chunked; + } + break; + + case h_matching_connection_token_start: + /* looking for 'Connection: keep-alive' */ + if (c == 'k') { + h_state = h_matching_connection_keep_alive; + /* looking for 'Connection: close' */ + } else if (c == 'c') { + h_state = h_matching_connection_close; + } else if (c == 'u') { + h_state = h_matching_connection_upgrade; + } else if (STRICT_TOKEN(c)) { + h_state = h_matching_connection_token; + } else if (c == ' ' || c == '\t') { + /* Skip lws */ + } else { + h_state = h_general; + } + break; + + /* looking for 'Connection: keep-alive' */ + case h_matching_connection_keep_alive: + parser->index++; + if (parser->index > sizeof(KEEP_ALIVE)-1 + || c != KEEP_ALIVE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(KEEP_ALIVE)-2) { + h_state = h_connection_keep_alive; + } + break; + + /* looking for 'Connection: close' */ + case h_matching_connection_close: + parser->index++; + if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(CLOSE)-2) { + h_state = h_connection_close; + } + break; + + /* looking for 'Connection: upgrade' */ + case h_matching_connection_upgrade: + parser->index++; + if (parser->index > sizeof(UPGRADE) - 1 || + c != UPGRADE[parser->index]) { + h_state = h_matching_connection_token; + } else if (parser->index == sizeof(UPGRADE)-2) { + h_state = h_connection_upgrade; + } + break; + + case h_matching_connection_token: + if (ch == ',') { + h_state = h_matching_connection_token_start; + parser->index = 0; + } + break; + + case h_transfer_encoding_chunked: + if (ch != ' ') h_state = h_general; + break; + + case h_connection_keep_alive: + case h_connection_close: + case h_connection_upgrade: + if (ch == ',') { + if (h_state == h_connection_keep_alive) { + parser->flags |= F_CONNECTION_KEEP_ALIVE; + } else if (h_state == h_connection_close) { + parser->flags |= F_CONNECTION_CLOSE; + } else if (h_state == h_connection_upgrade) { + parser->flags |= F_CONNECTION_UPGRADE; + } + h_state = h_matching_connection_token_start; + parser->index = 0; + } else if (ch != ' ') { + h_state = h_matching_connection_token; + } + break; + + default: + UPDATE_STATE(s_header_value); + h_state = h_general; + break; + } + } + parser->header_state = h_state; + + COUNT_HEADER_SIZE(p - start); + + if (p == data + len) + --p; + break; + } + + case s_header_almost_done: + { + if (UNLIKELY(ch != LF)) { + SET_ERRNO(HPE_LF_EXPECTED); + goto error; + } + + UPDATE_STATE(s_header_value_lws); + break; + } + + case s_header_value_lws: + { + if (ch == ' ' || ch == '\t') { + UPDATE_STATE(s_header_value_start); + REEXECUTE(); + } + + /* finished the header */ + switch (parser->header_state) { + case h_connection_keep_alive: + parser->flags |= F_CONNECTION_KEEP_ALIVE; + break; + case h_connection_close: + parser->flags |= F_CONNECTION_CLOSE; + break; + case h_transfer_encoding_chunked: + parser->flags |= F_CHUNKED; + break; + case h_connection_upgrade: + parser->flags |= F_CONNECTION_UPGRADE; + break; + default: + break; + } + + UPDATE_STATE(s_header_field_start); + REEXECUTE(); + } + + case s_header_value_discard_ws_almost_done: + { + STRICT_CHECK(ch != LF); + UPDATE_STATE(s_header_value_discard_lws); + break; + } + + case s_header_value_discard_lws: + { + if (ch == ' ' || ch == '\t') { + UPDATE_STATE(s_header_value_discard_ws); + break; + } else { + switch (parser->header_state) { + case h_connection_keep_alive: + parser->flags |= F_CONNECTION_KEEP_ALIVE; + break; + case h_connection_close: + parser->flags |= F_CONNECTION_CLOSE; + break; + case h_connection_upgrade: + parser->flags |= F_CONNECTION_UPGRADE; + break; + case h_transfer_encoding_chunked: + parser->flags |= F_CHUNKED; + break; + default: + break; + } + + /* header value was empty */ + MARK(header_value); + UPDATE_STATE(s_header_field_start); + CALLBACK_DATA_NOADVANCE(header_value); + REEXECUTE(); + } + } + + case s_headers_almost_done: + { + STRICT_CHECK(ch != LF); + + if (parser->flags & F_TRAILING) { + /* End of a chunked request */ + UPDATE_STATE(s_message_done); + CALLBACK_NOTIFY_NOADVANCE(chunk_complete); + REEXECUTE(); + } + + /* Cannot use chunked encoding and a content-length header together + per the HTTP specification. */ + if ((parser->flags & F_CHUNKED) && + (parser->flags & F_CONTENTLENGTH)) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } + + UPDATE_STATE(s_headers_done); + + /* Set this here so that on_headers_complete() callbacks can see it */ + if ((parser->flags & F_UPGRADE) && + (parser->flags & F_CONNECTION_UPGRADE)) { + /* For responses, "Upgrade: foo" and "Connection: upgrade" are + * mandatory only when it is a 101 Switching Protocols response, + * otherwise it is purely informational, to announce support. + */ + parser->upgrade = + (parser->type == HTTP_REQUEST || parser->status_code == 101); + } else { + parser->upgrade = (parser->method == HTTP_CONNECT); + } + + /* Here we call the headers_complete callback. This is somewhat + * different than other callbacks because if the user returns 1, we + * will interpret that as saying that this message has no body. This + * is needed for the annoying case of recieving a response to a HEAD + * request. + * + * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so + * we have to simulate it by handling a change in errno below. + */ + if (settings->on_headers_complete) { + switch (settings->on_headers_complete(parser)) { + case 0: + break; + + case 2: + parser->upgrade = 1; + + /* FALLTHROUGH */ + case 1: + parser->flags |= F_SKIPBODY; + break; + + default: + SET_ERRNO(HPE_CB_headers_complete); + RETURN(p - data); /* Error */ + } + } + + if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { + RETURN(p - data); + } + + REEXECUTE(); + } + + case s_headers_done: + { + int hasBody; + STRICT_CHECK(ch != LF); + + parser->nread = 0; + + hasBody = parser->flags & F_CHUNKED || + (parser->content_length > 0 && parser->content_length != ULLONG_MAX); + if (parser->upgrade && (parser->method == HTTP_CONNECT || + (parser->flags & F_SKIPBODY) || !hasBody)) { + /* Exit, the rest of the message is in a different protocol. */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + RETURN((p - data) + 1); + } + + if (parser->flags & F_SKIPBODY) { + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else if (parser->flags & F_CHUNKED) { + /* chunked encoding - ignore Content-Length header */ + UPDATE_STATE(s_chunk_size_start); + } else { + if (parser->content_length == 0) { + /* Content-Length header given but zero: Content-Length: 0\r\n */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else if (parser->content_length != ULLONG_MAX) { + /* Content-Length header given and non-zero */ + UPDATE_STATE(s_body_identity); + } else { + if (!http_message_needs_eof(parser)) { + /* Assume content-length 0 - read the next */ + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + } else { + /* Read body until EOF */ + UPDATE_STATE(s_body_identity_eof); + } + } + } + + break; + } + + case s_body_identity: + { + uint64_t to_read = MIN(parser->content_length, + (uint64_t) ((data + len) - p)); + + assert(parser->content_length != 0 + && parser->content_length != ULLONG_MAX); + + /* The difference between advancing content_length and p is because + * the latter will automaticaly advance on the next loop iteration. + * Further, if content_length ends up at 0, we want to see the last + * byte again for our message complete callback. + */ + MARK(body); + parser->content_length -= to_read; + p += to_read - 1; + + if (parser->content_length == 0) { + UPDATE_STATE(s_message_done); + + /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte. + * + * The alternative to doing this is to wait for the next byte to + * trigger the data callback, just as in every other case. The + * problem with this is that this makes it difficult for the test + * harness to distinguish between complete-on-EOF and + * complete-on-length. It's not clear that this distinction is + * important for applications, but let's keep it for now. + */ + CALLBACK_DATA_(body, p - body_mark + 1, p - data); + REEXECUTE(); + } + + break; + } + + /* read until EOF */ + case s_body_identity_eof: + MARK(body); + p = data + len - 1; + + break; + + case s_message_done: + UPDATE_STATE(NEW_MESSAGE()); + CALLBACK_NOTIFY(message_complete); + if (parser->upgrade) { + /* Exit, the rest of the message is in a different protocol. */ + RETURN((p - data) + 1); + } + break; + + case s_chunk_size_start: + { + assert(parser->nread == 1); + assert(parser->flags & F_CHUNKED); + + unhex_val = unhex[(unsigned char)ch]; + if (UNLIKELY(unhex_val == -1)) { + SET_ERRNO(HPE_INVALID_CHUNK_SIZE); + goto error; + } + + parser->content_length = unhex_val; + UPDATE_STATE(s_chunk_size); + break; + } + + case s_chunk_size: + { + uint64_t t; + + assert(parser->flags & F_CHUNKED); + + if (ch == CR) { + UPDATE_STATE(s_chunk_size_almost_done); + break; + } + + unhex_val = unhex[(unsigned char)ch]; + + if (unhex_val == -1) { + if (ch == ';' || ch == ' ') { + UPDATE_STATE(s_chunk_parameters); + break; + } + + SET_ERRNO(HPE_INVALID_CHUNK_SIZE); + goto error; + } + + t = parser->content_length; + t *= 16; + t += unhex_val; + + /* Overflow? Test against a conservative limit for simplicity. */ + if (UNLIKELY((ULLONG_MAX - 16) / 16 < parser->content_length)) { + SET_ERRNO(HPE_INVALID_CONTENT_LENGTH); + goto error; + } + + parser->content_length = t; + break; + } + + case s_chunk_parameters: + { + assert(parser->flags & F_CHUNKED); + /* just ignore this shit. TODO check for overflow */ + if (ch == CR) { + UPDATE_STATE(s_chunk_size_almost_done); + break; + } + break; + } + + case s_chunk_size_almost_done: + { + assert(parser->flags & F_CHUNKED); + STRICT_CHECK(ch != LF); + + parser->nread = 0; + + if (parser->content_length == 0) { + parser->flags |= F_TRAILING; + UPDATE_STATE(s_header_field_start); + } else { + UPDATE_STATE(s_chunk_data); + } + CALLBACK_NOTIFY(chunk_header); + break; + } + + case s_chunk_data: + { + uint64_t to_read = MIN(parser->content_length, + (uint64_t) ((data + len) - p)); + + assert(parser->flags & F_CHUNKED); + assert(parser->content_length != 0 + && parser->content_length != ULLONG_MAX); + + /* See the explanation in s_body_identity for why the content + * length and data pointers are managed this way. + */ + MARK(body); + parser->content_length -= to_read; + p += to_read - 1; + + if (parser->content_length == 0) { + UPDATE_STATE(s_chunk_data_almost_done); + } + + break; + } + + case s_chunk_data_almost_done: + assert(parser->flags & F_CHUNKED); + assert(parser->content_length == 0); + STRICT_CHECK(ch != CR); + UPDATE_STATE(s_chunk_data_done); + CALLBACK_DATA(body); + break; + + case s_chunk_data_done: + assert(parser->flags & F_CHUNKED); + STRICT_CHECK(ch != LF); + parser->nread = 0; + UPDATE_STATE(s_chunk_size_start); + CALLBACK_NOTIFY(chunk_complete); + break; + + default: + assert(0 && "unhandled state"); + SET_ERRNO(HPE_INVALID_INTERNAL_STATE); + goto error; + } + } + + /* Run callbacks for any marks that we have leftover after we ran our of + * bytes. There should be at most one of these set, so it's OK to invoke + * them in series (unset marks will not result in callbacks). + * + * We use the NOADVANCE() variety of callbacks here because 'p' has already + * overflowed 'data' and this allows us to correct for the off-by-one that + * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p' + * value that's in-bounds). + */ + + assert(((header_field_mark ? 1 : 0) + + (header_value_mark ? 1 : 0) + + (url_mark ? 1 : 0) + + (body_mark ? 1 : 0) + + (status_mark ? 1 : 0)) <= 1); + + CALLBACK_DATA_NOADVANCE(header_field); + CALLBACK_DATA_NOADVANCE(header_value); + CALLBACK_DATA_NOADVANCE(url); + CALLBACK_DATA_NOADVANCE(body); + CALLBACK_DATA_NOADVANCE(status); + + RETURN(len); + +error: + if (HTTP_PARSER_ERRNO(parser) == HPE_OK) { + SET_ERRNO(HPE_UNKNOWN); + } + + RETURN(p - data); +} + + +/* Does the parser need to see an EOF to find the end of the message? */ +int +http_message_needs_eof (const http_parser *parser) +{ + if (parser->type == HTTP_REQUEST) { + return 0; + } + + /* See RFC 2616 section 4.4 */ + if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */ + parser->status_code == 204 || /* No Content */ + parser->status_code == 304 || /* Not Modified */ + parser->flags & F_SKIPBODY) { /* response to a HEAD request */ + return 0; + } + + if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) { + return 0; + } + + return 1; +} + + +int +http_should_keep_alive (const http_parser *parser) +{ + if (parser->http_major > 0 && parser->http_minor > 0) { + /* HTTP/1.1 */ + if (parser->flags & F_CONNECTION_CLOSE) { + return 0; + } + } else { + /* HTTP/1.0 or earlier */ + if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) { + return 0; + } + } + + return !http_message_needs_eof(parser); +} + + +const char * +http_method_str (enum http_method m) +{ + return ELEM_AT(method_strings, m, ""); +} + + +void +http_parser_init (http_parser *parser, enum http_parser_type t) +{ + void *data = parser->data; /* preserve application data */ + memset(parser, 0, sizeof(*parser)); + parser->data = data; + parser->type = t; + parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res)); + parser->http_errno = HPE_OK; +} + +void +http_parser_settings_init(http_parser_settings *settings) +{ + memset(settings, 0, sizeof(*settings)); +} + +const char * +http_errno_name(enum http_errno err) { + assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); + return http_strerror_tab[err].name; +} + +const char * +http_errno_description(enum http_errno err) { + assert(((size_t) err) < ARRAY_SIZE(http_strerror_tab)); + return http_strerror_tab[err].description; +} + +static enum http_host_state +http_parse_host_char(enum http_host_state s, const char ch) { + switch(s) { + case s_http_userinfo: + case s_http_userinfo_start: + if (ch == '@') { + return s_http_host_start; + } + + if (IS_USERINFO_CHAR(ch)) { + return s_http_userinfo; + } + break; + + case s_http_host_start: + if (ch == '[') { + return s_http_host_v6_start; + } + + if (IS_HOST_CHAR(ch)) { + return s_http_host; + } + + break; + + case s_http_host: + if (IS_HOST_CHAR(ch)) { + return s_http_host; + } + + /* FALLTHROUGH */ + case s_http_host_v6_end: + if (ch == ':') { + return s_http_host_port_start; + } + + break; + + case s_http_host_v6: + if (ch == ']') { + return s_http_host_v6_end; + } + + /* FALLTHROUGH */ + case s_http_host_v6_start: + if (IS_HEX(ch) || ch == ':' || ch == '.') { + return s_http_host_v6; + } + + if (s == s_http_host_v6 && ch == '%') { + return s_http_host_v6_zone_start; + } + break; + + case s_http_host_v6_zone: + if (ch == ']') { + return s_http_host_v6_end; + } + + /* FALLTHROUGH */ + case s_http_host_v6_zone_start: + /* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */ + if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' || + ch == '~') { + return s_http_host_v6_zone; + } + break; + + case s_http_host_port: + case s_http_host_port_start: + if (IS_NUM(ch)) { + return s_http_host_port; + } + + break; + + default: + break; + } + return s_http_host_dead; +} + +static int +http_parse_host(const char * buf, struct http_parser_url *u, int found_at) { + enum http_host_state s; + + const char *p; + size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len; + + assert(u->field_set & (1 << UF_HOST)); + + u->field_data[UF_HOST].len = 0; + + s = found_at ? s_http_userinfo_start : s_http_host_start; + + for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) { + enum http_host_state new_s = http_parse_host_char(s, *p); + + if (new_s == s_http_host_dead) { + return 1; + } + + switch(new_s) { + case s_http_host: + if (s != s_http_host) { + u->field_data[UF_HOST].off = p - buf; + } + u->field_data[UF_HOST].len++; + break; + + case s_http_host_v6: + if (s != s_http_host_v6) { + u->field_data[UF_HOST].off = p - buf; + } + u->field_data[UF_HOST].len++; + break; + + case s_http_host_v6_zone_start: + case s_http_host_v6_zone: + u->field_data[UF_HOST].len++; + break; + + case s_http_host_port: + if (s != s_http_host_port) { + u->field_data[UF_PORT].off = p - buf; + u->field_data[UF_PORT].len = 0; + u->field_set |= (1 << UF_PORT); + } + u->field_data[UF_PORT].len++; + break; + + case s_http_userinfo: + if (s != s_http_userinfo) { + u->field_data[UF_USERINFO].off = p - buf ; + u->field_data[UF_USERINFO].len = 0; + u->field_set |= (1 << UF_USERINFO); + } + u->field_data[UF_USERINFO].len++; + break; + + default: + break; + } + s = new_s; + } + + /* Make sure we don't end somewhere unexpected */ + switch (s) { + case s_http_host_start: + case s_http_host_v6_start: + case s_http_host_v6: + case s_http_host_v6_zone_start: + case s_http_host_v6_zone: + case s_http_host_port_start: + case s_http_userinfo: + case s_http_userinfo_start: + return 1; + default: + break; + } + + return 0; +} + +void +http_parser_url_init(struct http_parser_url *u) { + memset(u, 0, sizeof(*u)); +} + +int +http_parser_parse_url(const char *buf, size_t buflen, int is_connect, + struct http_parser_url *u) +{ + enum state s; + const char *p; + enum http_parser_url_fields uf, old_uf; + int found_at = 0; + + u->port = u->field_set = 0; + s = is_connect ? s_req_server_start : s_req_spaces_before_url; + old_uf = UF_MAX; + + for (p = buf; p < buf + buflen; p++) { + s = parse_url_char(s, *p); + + /* Figure out the next field that we're operating on */ + switch (s) { + case s_dead: + return 1; + + /* Skip delimeters */ + case s_req_schema_slash: + case s_req_schema_slash_slash: + case s_req_server_start: + case s_req_query_string_start: + case s_req_fragment_start: + continue; + + case s_req_schema: + uf = UF_SCHEMA; + break; + + case s_req_server_with_at: + found_at = 1; + + /* FALLTHROUGH */ + case s_req_server: + uf = UF_HOST; + break; + + case s_req_path: + uf = UF_PATH; + break; + + case s_req_query_string: + uf = UF_QUERY; + break; + + case s_req_fragment: + uf = UF_FRAGMENT; + break; + + default: + assert(!"Unexpected state"); + return 1; + } + + /* Nothing's changed; soldier on */ + if (uf == old_uf) { + u->field_data[uf].len++; + continue; + } + + u->field_data[uf].off = p - buf; + u->field_data[uf].len = 1; + + u->field_set |= (1 << uf); + old_uf = uf; + } + + /* host must be present if there is a schema */ + /* parsing http:///toto will fail */ + if ((u->field_set & (1 << UF_SCHEMA)) && + (u->field_set & (1 << UF_HOST)) == 0) { + return 1; + } + + if (u->field_set & (1 << UF_HOST)) { + if (http_parse_host(buf, u, found_at) != 0) { + return 1; + } + } + + /* CONNECT requests can only contain "hostname:port" */ + if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) { + return 1; + } + + if (u->field_set & (1 << UF_PORT)) { + uint16_t off; + uint16_t len; + const char* p; + const char* end; + unsigned long v; + + off = u->field_data[UF_PORT].off; + len = u->field_data[UF_PORT].len; + end = buf + off + len; + + /* NOTE: The characters are already validated and are in the [0-9] range */ + assert(off + len <= buflen && "Port number overflow"); + v = 0; + for (p = buf + off; p < end; p++) { + v *= 10; + v += *p - '0'; + + /* Ports have a max value of 2^16 */ + if (v > 0xffff) { + return 1; + } + } + + u->port = (uint16_t) v; + } + + return 0; +} + +void +http_parser_pause(http_parser *parser, int paused) { + /* Users should only be pausing/unpausing a parser that is not in an error + * state. In non-debug builds, there's not much that we can do about this + * other than ignore it. + */ + if (HTTP_PARSER_ERRNO(parser) == HPE_OK || + HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) { + SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK); + } else { + assert(0 && "Attempting to pause parser in error state"); + } +} + +int +http_body_is_final(const struct http_parser *parser) { + return parser->state == s_message_done; +} + +unsigned long +http_parser_version(void) { + return HTTP_PARSER_VERSION_MAJOR * 0x10000 | + HTTP_PARSER_VERSION_MINOR * 0x00100 | + HTTP_PARSER_VERSION_PATCH * 0x00001; +} diff --git a/protocol/http_parser.h b/protocol/http_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..1fbf30e2b4740b9f4b1aef2bef53da142bf0b3ec --- /dev/null +++ b/protocol/http_parser.h @@ -0,0 +1,433 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ +#ifndef http_parser_h +#define http_parser_h +#ifdef __cplusplus +extern "C" { +#endif + +/* Also update SONAME in the Makefile whenever you change these. */ +#define HTTP_PARSER_VERSION_MAJOR 2 +#define HTTP_PARSER_VERSION_MINOR 8 +#define HTTP_PARSER_VERSION_PATCH 0 + +#include +#if defined(_WIN32) && !defined(__MINGW32__) && \ + (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) +#include +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +#include +#endif + +/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run + * faster + */ +#ifndef HTTP_PARSER_STRICT +# define HTTP_PARSER_STRICT 1 +#endif + +/* Maximium header size allowed. If the macro is not defined + * before including this header then the default is used. To + * change the maximum header size, define the macro in the build + * environment (e.g. -DHTTP_MAX_HEADER_SIZE=). To remove + * the effective limit on the size of the header, define the macro + * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) + */ +#ifndef HTTP_MAX_HEADER_SIZE +# define HTTP_MAX_HEADER_SIZE (80*1024) +#endif + +typedef struct http_parser http_parser; +typedef struct http_parser_settings http_parser_settings; + + +/* Callbacks should return non-zero to indicate an error. The parser will + * then halt execution. + * + * The one exception is on_headers_complete. In a HTTP_RESPONSE parser + * returning '1' from on_headers_complete will tell the parser that it + * should not expect a body. This is used when receiving a response to a + * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: + * chunked' headers that indicate the presence of a body. + * + * Returning `2` from on_headers_complete will tell parser that it should not + * expect neither a body nor any futher responses on this connection. This is + * useful for handling responses to a CONNECT request which may not contain + * `Upgrade` or `Connection: upgrade` headers. + * + * http_data_cb does not return data chunks. It will be called arbitrarily + * many times for each string. E.G. you might get 10 callbacks for "on_url" + * each providing just a few characters more data. + */ +typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); +typedef int (*http_cb) (http_parser*); + + +/* Status Codes */ +#define HTTP_STATUS_MAP(XX) \ + XX(100, CONTINUE, Continue) \ + XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \ + XX(102, PROCESSING, Processing) \ + XX(200, OK, OK) \ + XX(201, CREATED, Created) \ + XX(202, ACCEPTED, Accepted) \ + XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \ + XX(204, NO_CONTENT, No Content) \ + XX(205, RESET_CONTENT, Reset Content) \ + XX(206, PARTIAL_CONTENT, Partial Content) \ + XX(207, MULTI_STATUS, Multi-Status) \ + XX(208, ALREADY_REPORTED, Already Reported) \ + XX(226, IM_USED, IM Used) \ + XX(300, MULTIPLE_CHOICES, Multiple Choices) \ + XX(301, MOVED_PERMANENTLY, Moved Permanently) \ + XX(302, FOUND, Found) \ + XX(303, SEE_OTHER, See Other) \ + XX(304, NOT_MODIFIED, Not Modified) \ + XX(305, USE_PROXY, Use Proxy) \ + XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \ + XX(308, PERMANENT_REDIRECT, Permanent Redirect) \ + XX(400, BAD_REQUEST, Bad Request) \ + XX(401, UNAUTHORIZED, Unauthorized) \ + XX(402, PAYMENT_REQUIRED, Payment Required) \ + XX(403, FORBIDDEN, Forbidden) \ + XX(404, NOT_FOUND, Not Found) \ + XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \ + XX(406, NOT_ACCEPTABLE, Not Acceptable) \ + XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \ + XX(408, REQUEST_TIMEOUT, Request Timeout) \ + XX(409, CONFLICT, Conflict) \ + XX(410, GONE, Gone) \ + XX(411, LENGTH_REQUIRED, Length Required) \ + XX(412, PRECONDITION_FAILED, Precondition Failed) \ + XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \ + XX(414, URI_TOO_LONG, URI Too Long) \ + XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \ + XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \ + XX(417, EXPECTATION_FAILED, Expectation Failed) \ + XX(421, MISDIRECTED_REQUEST, Misdirected Request) \ + XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \ + XX(423, LOCKED, Locked) \ + XX(424, FAILED_DEPENDENCY, Failed Dependency) \ + XX(426, UPGRADE_REQUIRED, Upgrade Required) \ + XX(428, PRECONDITION_REQUIRED, Precondition Required) \ + XX(429, TOO_MANY_REQUESTS, Too Many Requests) \ + XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \ + XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \ + XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \ + XX(501, NOT_IMPLEMENTED, Not Implemented) \ + XX(502, BAD_GATEWAY, Bad Gateway) \ + XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \ + XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \ + XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \ + XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \ + XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \ + XX(508, LOOP_DETECTED, Loop Detected) \ + XX(510, NOT_EXTENDED, Not Extended) \ + XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \ + +enum http_status + { +#define XX(num, name, string) HTTP_STATUS_##name = num, + HTTP_STATUS_MAP(XX) +#undef XX + }; + + +/* Request Methods */ +#define HTTP_METHOD_MAP(XX) \ + XX(0, DELETE, DELETE) \ + XX(1, GET, GET) \ + XX(2, HEAD, HEAD) \ + XX(3, POST, POST) \ + XX(4, PUT, PUT) \ + /* pathological */ \ + XX(5, CONNECT, CONNECT) \ + XX(6, OPTIONS, OPTIONS) \ + XX(7, TRACE, TRACE) \ + /* WebDAV */ \ + XX(8, COPY, COPY) \ + XX(9, LOCK, LOCK) \ + XX(10, MKCOL, MKCOL) \ + XX(11, MOVE, MOVE) \ + XX(12, PROPFIND, PROPFIND) \ + XX(13, PROPPATCH, PROPPATCH) \ + XX(14, SEARCH, SEARCH) \ + XX(15, UNLOCK, UNLOCK) \ + XX(16, BIND, BIND) \ + XX(17, REBIND, REBIND) \ + XX(18, UNBIND, UNBIND) \ + XX(19, ACL, ACL) \ + /* subversion */ \ + XX(20, REPORT, REPORT) \ + XX(21, MKACTIVITY, MKACTIVITY) \ + XX(22, CHECKOUT, CHECKOUT) \ + XX(23, MERGE, MERGE) \ + /* upnp */ \ + XX(24, MSEARCH, M-SEARCH) \ + XX(25, NOTIFY, NOTIFY) \ + XX(26, SUBSCRIBE, SUBSCRIBE) \ + XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ + /* RFC-5789 */ \ + XX(28, PATCH, PATCH) \ + XX(29, PURGE, PURGE) \ + /* CalDAV */ \ + XX(30, MKCALENDAR, MKCALENDAR) \ + /* RFC-2068, section 19.6.1.2 */ \ + XX(31, LINK, LINK) \ + XX(32, UNLINK, UNLINK) \ + /* icecast */ \ + XX(33, SOURCE, SOURCE) \ + +enum http_method + { +#define XX(num, name, string) HTTP_##name = num, + HTTP_METHOD_MAP(XX) +#undef XX + }; + + +enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; + + +/* Flag values for http_parser.flags field */ +enum flags + { F_CHUNKED = 1 << 0 + , F_CONNECTION_KEEP_ALIVE = 1 << 1 + , F_CONNECTION_CLOSE = 1 << 2 + , F_CONNECTION_UPGRADE = 1 << 3 + , F_TRAILING = 1 << 4 + , F_UPGRADE = 1 << 5 + , F_SKIPBODY = 1 << 6 + , F_CONTENTLENGTH = 1 << 7 + }; + + +/* Map for errno-related constants + * + * The provided argument should be a macro that takes 2 arguments. + */ +#define HTTP_ERRNO_MAP(XX) \ + /* No error */ \ + XX(OK, "success") \ + \ + /* Callback-related errors */ \ + XX(CB_message_begin, "the on_message_begin callback failed") \ + XX(CB_url, "the on_url callback failed") \ + XX(CB_header_field, "the on_header_field callback failed") \ + XX(CB_header_value, "the on_header_value callback failed") \ + XX(CB_headers_complete, "the on_headers_complete callback failed") \ + XX(CB_body, "the on_body callback failed") \ + XX(CB_message_complete, "the on_message_complete callback failed") \ + XX(CB_status, "the on_status callback failed") \ + XX(CB_chunk_header, "the on_chunk_header callback failed") \ + XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ + \ + /* Parsing-related errors */ \ + XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ + XX(HEADER_OVERFLOW, \ + "too many header bytes seen; overflow detected") \ + XX(CLOSED_CONNECTION, \ + "data received after completed connection: close message") \ + XX(INVALID_VERSION, "invalid HTTP version") \ + XX(INVALID_STATUS, "invalid HTTP status code") \ + XX(INVALID_METHOD, "invalid HTTP method") \ + XX(INVALID_URL, "invalid URL") \ + XX(INVALID_HOST, "invalid host") \ + XX(INVALID_PORT, "invalid port") \ + XX(INVALID_PATH, "invalid path") \ + XX(INVALID_QUERY_STRING, "invalid query string") \ + XX(INVALID_FRAGMENT, "invalid fragment") \ + XX(LF_EXPECTED, "LF character expected") \ + XX(INVALID_HEADER_TOKEN, "invalid character in header") \ + XX(INVALID_CONTENT_LENGTH, \ + "invalid character in content-length header") \ + XX(UNEXPECTED_CONTENT_LENGTH, \ + "unexpected content-length header") \ + XX(INVALID_CHUNK_SIZE, \ + "invalid character in chunk size header") \ + XX(INVALID_CONSTANT, "invalid constant string") \ + XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ + XX(STRICT, "strict mode assertion failed") \ + XX(PAUSED, "parser is paused") \ + XX(UNKNOWN, "an unknown error occurred") + + +/* Define HPE_* values for each errno value above */ +#define HTTP_ERRNO_GEN(n, s) HPE_##n, +enum http_errno { + HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) +}; +#undef HTTP_ERRNO_GEN + + +/* Get an http_errno value from an http_parser */ +#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) + + +struct http_parser { + /** PRIVATE **/ + unsigned int type : 2; /* enum http_parser_type */ + unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ + unsigned int state : 7; /* enum state from http_parser.c */ + unsigned int header_state : 7; /* enum header_state from http_parser.c */ + unsigned int index : 7; /* index into current matcher */ + unsigned int lenient_http_headers : 1; + + uint32_t nread; /* # bytes read in various scenarios */ + uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ + + /** READ-ONLY **/ + unsigned short http_major; + unsigned short http_minor; + unsigned int status_code : 16; /* responses only */ + unsigned int method : 8; /* requests only */ + unsigned int http_errno : 7; + + /* 1 = Upgrade header was present and the parser has exited because of that. + * 0 = No upgrade header present. + * Should be checked when http_parser_execute() returns in addition to + * error checking. + */ + unsigned int upgrade : 1; + + /** PUBLIC **/ + void *data; /* A pointer to get hook to the "connection" or "socket" object */ +}; + + +struct http_parser_settings { + http_cb on_message_begin; + http_data_cb on_url; + http_data_cb on_status; + http_data_cb on_header_field; + http_data_cb on_header_value; + http_cb on_headers_complete; + http_data_cb on_body; + http_cb on_message_complete; + /* When on_chunk_header is called, the current chunk length is stored + * in parser->content_length. + */ + http_cb on_chunk_header; + http_cb on_chunk_complete; +}; + + +enum http_parser_url_fields + { UF_SCHEMA = 0 + , UF_HOST = 1 + , UF_PORT = 2 + , UF_PATH = 3 + , UF_QUERY = 4 + , UF_FRAGMENT = 5 + , UF_USERINFO = 6 + , UF_MAX = 7 + }; + + +/* Result structure for http_parser_parse_url(). + * + * Callers should index into field_data[] with UF_* values iff field_set + * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and + * because we probably have padding left over), we convert any port to + * a uint16_t. + */ +struct http_parser_url { + uint16_t field_set; /* Bitmask of (1 << UF_*) values */ + uint16_t port; /* Converted UF_PORT string */ + + struct { + uint16_t off; /* Offset into buffer in which field starts */ + uint16_t len; /* Length of run in buffer */ + } field_data[UF_MAX]; +}; + + +/* Returns the library version. Bits 16-23 contain the major version number, + * bits 8-15 the minor version number and bits 0-7 the patch level. + * Usage example: + * + * unsigned long version = http_parser_version(); + * unsigned major = (version >> 16) & 255; + * unsigned minor = (version >> 8) & 255; + * unsigned patch = version & 255; + * printf("http_parser v%u.%u.%u\n", major, minor, patch); + */ +unsigned long http_parser_version(void); + +void http_parser_init(http_parser *parser, enum http_parser_type type); + + +/* Initialize http_parser_settings members to 0 + */ +void http_parser_settings_init(http_parser_settings *settings); + + +/* Executes the parser. Returns number of parsed bytes. Sets + * `parser->http_errno` on error. */ +size_t http_parser_execute(http_parser *parser, + const http_parser_settings *settings, + const char *data, + size_t len); + + +/* If http_should_keep_alive() in the on_headers_complete or + * on_message_complete callback returns 0, then this should be + * the last message on the connection. + * If you are the server, respond with the "Connection: close" header. + * If you are the client, close the connection. + */ +int http_should_keep_alive(const http_parser *parser); + +/* Returns a string version of the HTTP method. */ +const char *http_method_str(enum http_method m); + +/* Return a string name of the given error */ +const char *http_errno_name(enum http_errno err); + +/* Return a string description of the given error */ +const char *http_errno_description(enum http_errno err); + +/* Initialize all http_parser_url members to 0 */ +void http_parser_url_init(struct http_parser_url *u); + +/* Parse a URL; return nonzero on failure */ +int http_parser_parse_url(const char *buf, size_t buflen, + int is_connect, + struct http_parser_url *u); + +/* Pause or un-pause the parser; a nonzero value pauses */ +void http_parser_pause(http_parser *parser, int paused); + +/* Checks if this is the final chunk of the body. */ +int http_body_is_final(const http_parser *parser); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/protocol/httpcreatorimpl.cpp b/protocol/httpcreatorimpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f82d51e868f6f830d18e5318239f3d8902ecf7fb --- /dev/null +++ b/protocol/httpcreatorimpl.cpp @@ -0,0 +1,76 @@ +#include "httpcreatorimpl.h" +#include "httpimpl.h" + + +CHttpCreatorImpl::CHttpCreatorImpl(void) +{ + +} +CHttpCreatorImpl::~CHttpCreatorImpl(void) +{ + +} +////////////////////////////////////////////////////////////////////////// +std_method_impl CHttpCreatorImpl::init_class(IBase* prot, IBase* punkOuter) +{ + HRESULT hr = S_OK; + if (prot != NULL) + { + m_pRot = prot; + } + return hr; +} +std_method_impl CHttpCreatorImpl::Init(void*) +{ + HRESULT hr = S_OK; + + return hr; +} +std_method_impl CHttpCreatorImpl::Uninit() +{ + HRESULT hr = S_OK; + + return hr; +} +std_method_impl CHttpCreatorImpl::Start() +{ + HRESULT hr = S_OK; + + m_pRot->GetObject(CLSID_IAsynFrame, _uuidof(IAsynIo), (IBase**)&m_pIAsynIo.m_p); + retrtpv(m_pIAsynIo, E_FAIL) + + + m_pRot->GetObject(CLSID_IAsynFrame, _uuidof(IAsynFrame), (IBase**)&m_pIAsynFrame.m_p); + retrtpv(m_pIAsynFrame, E_FAIL) + + + return hr; +} +std_method_impl CHttpCreatorImpl::Stop() +{ + HRESULT hr = S_OK; + return hr; +} +std_method_impl CHttpCreatorImpl::CreateHttpClient(IBase **pBase) +{ + HRESULT hr = S_OK; + + _lComPtr pSocket = INULL; + _lComPtr ppOperation = INULL; + CHttpImpl* pObject = NULL; + m_pIAsynIo->CreateAsyncTcpSocket((IBase**)&pSocket.m_p); + pObject = new CHttpImpl(); + hr = pObject->QueryInterface(_uuidof(IHttp), (void**)pBase); + m_pIAsynFrame->CreateAsynIoOperation(&ppOperation.m_p, pObject); + pObject->BindOper(pSocket,ppOperation); + m_pIAsynFrame->PostAsynIoOperation(ppOperation); + + return hr; +} +std_method_impl CHttpCreatorImpl::CreateHttpServer(IBase **pBase) +{ + HRESULT hr = S_OK; + return hr; +} + + diff --git a/asynio/asynioimpl.h b/protocol/httpcreatorimpl.h similarity index 55% rename from asynio/asynioimpl.h rename to protocol/httpcreatorimpl.h index a7e5c6aacf91c79ea84942cdfd56e83dd2691fe3..a640455b51f355b106f9d4f805778fcc9582b7fd 100644 --- a/asynio/asynioimpl.h +++ b/protocol/httpcreatorimpl.h @@ -1,21 +1,22 @@ -#ifndef _ASYNIOIMPL_H_ -#define _ASYNIOIMPL_H_ +#ifndef _HTTPCREATORIMPL_H_ +#define _HTTPCREATORIMPL_H_ #include "stdafx.h" -#include +#include +#include -class CAsynIoImpl : public IAsynIo, - public IPlugin, - public IPluginRun, - public CUnknownImp +class CHttpCreatorImpl : public IHttpCreator, + public IPlugin, + public IPluginRun, + public CUnknownImp { public: - CAsynIoImpl(void); - virtual ~CAsynIoImpl(void); - + CHttpCreatorImpl(void); + virtual ~CHttpCreatorImpl(void); - UNKNOWN_IMP3_(IPlugin, IPluginRun,IAsynIo); + + UNKNOWN_IMP3_(IPlugin, IPluginRun, IHttpCreator); ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -30,20 +31,22 @@ public: ////////////////////////////////////////////////////////////////////////// std_method(Start)(); std_method(Stop)(); - ////////////////////////////////////////////////////////////////////////// - - - std_method(CreateReadFile)(IBase** pReadFile); - std_method(CreateWriteFile)(IBase** pWriteFile); - std_method(CreateAsyncTcpSocket)(IBase** pAsynTcpSocket); - std_method(CreateTcpSocket)(IBase** pTcpSocket); - std_method(CreateAsyncUdpSocket)(IBase** pAsynUdpSocket); - std_method(CreateUdpSocket)(IBase** pUdpSocket); - std_method(DeleteIo)(IBase* pAsynIo); + //IHttpCreator + std_method(CreateHttpClient)(IBase **pBase); + std_method(CreateHttpServer)(IBase **pBase); private: _lComPtr m_pRot; + _lComPtr m_pIAsynIo; + _lComPtr m_pIAsynFrame; }; + + + + + + + #endif \ No newline at end of file diff --git a/protocol/httpimpl.cpp b/protocol/httpimpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d37e310555172d97f0fd99d0abf1cf200513df7 --- /dev/null +++ b/protocol/httpimpl.cpp @@ -0,0 +1,67 @@ +#include "httpimpl.h" + + +CHttpImpl::CHttpImpl() +{ + +} +CHttpImpl::~CHttpImpl(void) +{ + +} +void CHttpImpl::BindOper(IAsyncTcpSocket* pSocket, IIoOperation* Oper) +{ + m_pIAsyncTcpSocket = pSocket; + m_pIOper = Oper; +} +////////////////////////////////////////////////////////////////////////// +std_method_impl CHttpImpl::Get() +{ + + const char* buf = "GET /home/index HTTP/1.1\r\n"; + const char* accpet = "Accept - Language: zh - CN\r\n"; + const char* accpetcode = "Accept - Encoding: gzip, deflate\r\n"; + const char* acceptlang = "Accept - Language: zh - CN\r\n"; + const char* ck = "Connection: Keep - Alive\r\n"; + const char* host = "Host: 127.0.0.1 : 8000\r\n"; + const char* ua = "User - Agent: Mozilla / 5.0 (Windows NT 10.0; Win64; x64) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome / 58.0.3029.110 Safari / 537.36 Edge / 16.16299\r\n\r\n"; + + while (1) { + m_pIAsyncTcpSocket->OpenIo(); + m_OperBehavior.type = addr_socket_v4; + string_strcpy(m_OperBehavior.address, "61.135.169.125"); + m_OperBehavior.port = 443; + m_OperBehavior.Object.socket = m_pIAsyncTcpSocket->GetSocket(); + m_pIOper->SetBind(m_OperBehavior); + m_pIOper->SetOpType(OP_TCPSOCKET_CONNECT); + m_pIAsyncTcpSocket->ConnectIo(m_pIOper.m_p); + TimeSleep(1); + } + return S_OK; +} +std_method_impl CHttpImpl::Post() +{ + return S_OK; +} + + +std_method_impl CHttpImpl::OnOperationComplete(IIoOperation *pOperation) +{ + ERROR_CODE errcode; + ULONG TransferedBytes = 0; + + pOperation->GetResult(&errcode, &TransferedBytes); + if (errcode == 0) + { + + } + else + { + //pOperation->Cancel(); + //m_pIAsyncTcpSocket->CloseIo(); + } + return S_OK; +} + + + diff --git a/protocol/httpimpl.h b/protocol/httpimpl.h new file mode 100644 index 0000000000000000000000000000000000000000..1c2c94b506cbdc82d74689c2d41be7f3545d18d5 --- /dev/null +++ b/protocol/httpimpl.h @@ -0,0 +1,40 @@ +#ifndef _HTTPIMPL_H_ +#define _HTTPIMPL_H_ + +#include "stdafx.h" +#include +#include + +class CHttpImpl : public IHttp, + public IIoOperationEvents, + public CUnknownImp +{ +public: + CHttpImpl(); + virtual ~CHttpImpl(void); +public: + void BindOper(IAsyncTcpSocket* pSocket,IIoOperation* Oper); + UNKNOWN_IMP1(IHttp); + ////////////////////////////////////////////////////////////////////////// + //IHttp + std_method(Get)(); + std_method(Post)(); + ////////////////////////////////////////////////////////////////////////// + //IIoOperationEvents + std_method(OnOperationComplete)(IIoOperation *pOperation); + ////////////////////////////////////////////////////////////////////////// +private: + _lComPtr m_pIAsyncTcpSocket; + _lComPtr m_pIOper; + OperationBehavior m_OperBehavior; + + +}; + + + + + + + +#endif \ No newline at end of file diff --git a/protocol/protocol.vcxproj b/protocol/protocol.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..3802414194b28dfed32f244c7643eb000ece100c --- /dev/null +++ b/protocol/protocol.vcxproj @@ -0,0 +1,141 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {1E152A99-DC53-4334-A44A-F623F5CB49C8} + Plugin + Win32Proj + 10.0.16299.0 + + + + DynamicLibrary + v141 + Unicode + true + + + DynamicLibrary + v141 + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25123.0 + + + $(SolutionDir)\bin\$(IntDir) + $(Configuration)\ + true + MinimumRecommendedRules.ruleset + + + + + $(SolutionDir)\bin\$(IntDir) + $(Configuration)\ + false + MinimumRecommendedRules.ruleset + + + + + + Disabled + ../include;../extensions/include;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_WINDOWS;_USRDLL;PLUGIN_EXPORTS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + NotUsing + Level3 + EditAndContinue + + + $(OutDir)\$(ProjectName).dll + ..\lib;%(AdditionalLibraryDirectories) + dllexports.def + true + ..\obj\$(IntDir)$(TargetName).pdb + Windows + ..\lib\$(IntDir)$(TargetName).lib + MachineX86 + + + + + MaxSpeed + true + ../include;../extensions/include;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;_USRDLL;PLUGIN_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + true + NotUsing + Level3 + ProgramDatabase + + + $(OutDir)\$(ProjectName).dll + ..\lib;%(AdditionalLibraryDirectories) + dllexports.def + true + ..\obj\$(IntDir)$(TargetName).pdb + Windows + true + true + ..\lib\$(IntDir)$(TargetName).lib + MachineX86 + + + + + + + + + + false + + + false + + + + + + Create + Create + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/protocol/stdafx.cpp b/protocol/stdafx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6df3550ce81cc351d786ce90d7c996762fce08ab --- /dev/null +++ b/protocol/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// Plugin.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/protocol/stdafx.h b/protocol/stdafx.h new file mode 100644 index 0000000000000000000000000000000000000000..0f2c0d7f86b6e301819d097dff60d953c4c755cc --- /dev/null +++ b/protocol/stdafx.h @@ -0,0 +1,20 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#ifndef _STDAFX_H_ +#define _STDAFX_H_ + +#include + +#include +#include +#include +#include +using namespace by; + +#include +#include + +#endif \ No newline at end of file diff --git a/protocol/targetver.h b/protocol/targetver.h new file mode 100644 index 0000000000000000000000000000000000000000..203dfbcf61107432f6b42793715d96f7b06d5802 --- /dev/null +++ b/protocol/targetver.h @@ -0,0 +1,24 @@ +#pragma once + +// The following macros define the minimum required platform. The minimum required platform +// is the earliest version of Windows, Internet Explorer etc. that has the necessary features to run +// your application. The macros work by enabling all features available on platform versions up to and +// including the version specified. + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. +#ifndef WINVER // Specifies that the minimum required platform is Windows Vista. +#define WINVER 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#ifndef _WIN32_WINDOWS // Specifies that the minimum required platform is Windows 98. +#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later. +#endif + +#ifndef _WIN32_IE // Specifies that the minimum required platform is Internet Explorer 7.0. +#define _WIN32_IE 0x0700 // Change this to the appropriate value to target other versions of IE. +#endif diff --git a/sshchannel/CMakeLists.txt b/sshchannel/CMakeLists.txt index 58e7419f4e05be27220b98fc7550bf74c620e748..41077c21939adac3d837d851be5e37bda48497e4 100644 --- a/sshchannel/CMakeLists.txt +++ b/sshchannel/CMakeLists.txt @@ -38,6 +38,8 @@ if(CMAKE_BUILD_TYPE STREQUAL Release) set_target_properties(sshchannel PROPERTIES COMPILE_FLAGS "-O3") endif() +target_link_libraries(sshchannel dl) +target_link_libraries(sshchannel pthread) install(TARGETS sshchannel LIBRARY DESTINATION bin diff --git a/sshchannel/sshchannelimpl.cpp b/sshchannel/sshchannelimpl.cpp index a831acce1898034246eeeeeb09930b0b453346b3..452743fc43c8af50963a82be4faa91fb72e80a89 100644 --- a/sshchannel/sshchannelimpl.cpp +++ b/sshchannel/sshchannelimpl.cpp @@ -1,5 +1,5 @@ #include "sshchannelimpl.h" - +#include CSshChannelImpl::CSshChannelImpl(void) { @@ -35,9 +35,20 @@ std_method_impl CSshChannelImpl::Start() { HRESULT hr = S_OK; - m_pRot->GetObject(CLSID_IAsynIo,_uuidof(IAsynIo),(IBase**)&m_pIAsynIo.m_p); + m_pRot->GetObject(CLSID_IAsynFrame,_uuidof(IAsynIo),(IBase**)&m_pIAsynIo.m_p); retrtpv(m_pIAsynIo,E_FAIL) + ithread::start_thread(); + + _lComPtr m_pIHttpCreator; + m_pRot->GetObject(CLSID_IHttp, _uuidof(IHttpCreator), (IBase**)&m_pIHttpCreator.m_p); + retrtpv(m_pIAsynIo, E_FAIL) + + _lComPtr m_pIHttp; + m_pIHttpCreator->CreateHttpClient((IBase**)&m_pIHttp); + m_pIHttp->Get(); + + return hr; } std_method_impl CSshChannelImpl::Stop() @@ -68,6 +79,20 @@ std_method_type_impl(ssize_t) CSshChannelImpl::RecvChannel(sshid id,char* buf,si return -1; } +void CSshChannelImpl::run() { + + _lComPtr m_pIHttpCreator; + m_pRot->GetObject(CLSID_IHttp, _uuidof(IHttpCreator), (IBase**)&m_pIHttpCreator.m_p); + + _lComPtr m_pIHttp; + m_pIHttpCreator->CreateHttpClient((IBase**)&m_pIHttp); + m_pIHttp->Get(); + +} +void CSshChannelImpl::threadstop() { + +} + diff --git a/sshchannel/sshchannelimpl.h b/sshchannel/sshchannelimpl.h index 339daadb798576588720e15f0aa09ee1ac16b1a4..e415884e9a60713c606cfdced29a3debc3ba0c70 100644 --- a/sshchannel/sshchannelimpl.h +++ b/sshchannel/sshchannelimpl.h @@ -4,12 +4,15 @@ #include "stdafx.h" #include #include -#include +#include +#include class CSshChannelImpl : public ISshChannel, public IPlugin, public IPluginRun, - public CUnknownImp + public CUnknownImp, + public ithread + { public: CSshChannelImpl(void); @@ -40,6 +43,10 @@ public: ////////////////////////////////////////////////////////////////////////// + + + void run(); + void threadstop(); private: _lComPtr m_pRot; _lComPtr m_pIAsynIo;