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;