diff --git a/CcRemote/.vs/CcRemote/v15/.suo b/CcRemote/.vs/CcRemote/v15/.suo index a936484..68e6677 100644 Binary files a/CcRemote/.vs/CcRemote/v15/.suo and b/CcRemote/.vs/CcRemote/v15/.suo differ diff --git a/CcRemote/CcRemote/CcRemote.vcxproj b/CcRemote/CcRemote/CcRemote.vcxproj index 96a23a1..d73496e 100644 --- a/CcRemote/CcRemote/CcRemote.vcxproj +++ b/CcRemote/CcRemote/CcRemote.vcxproj @@ -38,7 +38,7 @@ false v141 true - Unicode + MultiByte Static @@ -53,7 +53,7 @@ false v141 true - Unicode + MultiByte Static @@ -91,12 +91,14 @@ Use Level3 Disabled - true + false WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions) pch.h Windows + ..\..\common\zlib\zlib.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) false @@ -114,12 +116,14 @@ Use Level3 Disabled - true + false _WINDOWS;_DEBUG;%(PreprocessorDefinitions) pch.h Windows + ..\..\common\zlib\zlib.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) false @@ -139,14 +143,18 @@ MaxSpeed true true - true + false WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions) pch.h + MultiThreadedDebug Windows true true + ..\..\common\zlib\zlib.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + /SAFESEH:NO %(AdditionalOptions) false @@ -166,14 +174,18 @@ MaxSpeed true true - true + false _WINDOWS;NDEBUG;%(PreprocessorDefinitions) pch.h + MultiThreadedDebug Windows true true + ..\..\common\zlib\zlib.lib;%(AdditionalDependencies) + LIBCMT.lib;%(IgnoreSpecificDefaultLibraries) + /SAFESEH:NO %(AdditionalOptions) false @@ -190,6 +202,10 @@ + + + + @@ -199,6 +215,17 @@ + + NotUsing + NotUsing + NotUsing + + + + NotUsing + NotUsing + NotUsing + Create Create diff --git a/CcRemote/CcRemote/CcRemote.vcxproj.filters b/CcRemote/CcRemote/CcRemote.vcxproj.filters index 8ae751f..2e3a1f8 100644 --- a/CcRemote/CcRemote/CcRemote.vcxproj.filters +++ b/CcRemote/CcRemote/CcRemote.vcxproj.filters @@ -42,6 +42,18 @@ 重写控件 + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + @@ -56,6 +68,15 @@ 重写控件 + + 源文件 + + + 源文件 + + + 源文件 + diff --git a/CcRemote/CcRemote/CcRemoteDlg.cpp b/CcRemote/CcRemote/CcRemoteDlg.cpp index 8d92c88..94ef210 100644 --- a/CcRemote/CcRemote/CcRemoteDlg.cpp +++ b/CcRemote/CcRemote/CcRemoteDlg.cpp @@ -15,7 +15,7 @@ - +CIOCPServer *m_iocpServer = NULL; // 用于应用程序“关于”菜单项的 CAboutDlg 对话框 class CAboutDlg : public CDialogEx @@ -96,6 +96,78 @@ END_MESSAGE_MAP() // CCcRemoteDlg 消息处理程序 +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers +//NotifyProc是这个socket内核的核心 所有的关于socket 的处理都要调用这个函数 +void CALLBACK CCcRemoteDlg::NotifyProc(LPVOID lpParam, ClientContext *pContext, UINT nCode) +{ + try + { + switch (nCode) + { + case NC_CLIENT_CONNECT: + break; + case NC_CLIENT_DISCONNECT: + //g_pConnectView->PostMessage(WM_REMOVEFROMLIST, 0, (LPARAM)pContext); + break; + case NC_TRANSMIT: + break; + case NC_RECEIVE: + //ProcessReceive(pContext); //这里是有数据到来 但没有完全接收 + break; + case NC_RECEIVE_COMPLETE: + //ProcessReceiveComplete(pContext); //这里时完全接收 处理发送来的数据 跟进 ProcessReceiveComplete + break; + } + } + catch (...) {} +} + + +// 监听端口 最大上线个数 +void CCcRemoteDlg::Activate(UINT nPort, UINT nMaxConnections) +{ + CString str; + + if (m_iocpServer != NULL) + { + m_iocpServer->Shutdown(); + delete m_iocpServer; + + } + m_iocpServer = new CIOCPServer; + + // 开启IPCP服务器 最大连接 端口 查看NotifyProc回调函数 函数定义 + if (m_iocpServer->Initialize(NotifyProc, NULL, 100000, nPort)) + { + + char hostname[256]; + gethostname(hostname, sizeof(hostname)); + HOSTENT *host = gethostbyname(hostname); + if (host != NULL) + { + for (int i = 0; ; i++) + { + str += inet_ntoa(*(IN_ADDR*)host->h_addr_list[i]); + if (host->h_addr_list[i] + host->h_length >= host->h_name) + break; + str += "/"; + } + } + + + str.Format("监听端口: %d成功", nPort); + ShowMessage(true, str); + } + else + { + str.Format("监听端口: %d失败", nPort); + ShowMessage(true, str); + } + + //m_wndStatusBar.SetPaneText(3, "连接: 0"); +} + BOOL CCcRemoteDlg::OnInitDialog() { CDialogEx::OnInitDialog(); @@ -138,6 +210,7 @@ BOOL CCcRemoteDlg::OnInitDialog() rect.bottom += 20; MoveWindow(rect); //----------------------------------------| + Activate(2000,9999); Test(); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE diff --git a/CcRemote/CcRemote/CcRemoteDlg.h b/CcRemote/CcRemote/CcRemoteDlg.h index dff9cae..1941b49 100644 --- a/CcRemote/CcRemote/CcRemoteDlg.h +++ b/CcRemote/CcRemote/CcRemoteDlg.h @@ -3,6 +3,7 @@ // #include "TrueColorToolBar.h" #include "PublicStruct.h" +#include "include/IOCPServer.h" #pragma once @@ -82,7 +83,8 @@ private: void ShowMessage(bool bIsOK, CString strMsg); void Test(); - + static void CALLBACK NotifyProc(LPVOID lpParam, ClientContext* pContext, UINT nCode); + void Activate(UINT nPort, UINT nMaxConnections); public: //-------------自定义消息处理------------- diff --git a/CcRemote/CcRemote/Debug/CcRemote.Build.CppClean.log b/CcRemote/CcRemote/Debug/CcRemote.Build.CppClean.log index 1db3b7a..db472ff 100644 --- a/CcRemote/CcRemote/Debug/CcRemote.Build.CppClean.log +++ b/CcRemote/CcRemote/Debug/CcRemote.Build.CppClean.log @@ -1,20 +1,23 @@ -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.pch -f:\myapp\ccremote\ccremote\ccremote\debug\vc141.pdb -f:\myapp\ccremote\ccremote\ccremote\debug\vc141.idb -f:\myapp\ccremote\ccremote\ccremote\debug\pch.obj -f:\myapp\ccremote\ccremote\ccremote\debug\truecolortoolbar.obj -f:\myapp\ccremote\ccremote\ccremote\debug\ccremotedlg.obj -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.obj -f:\myapp\ccremote\ccremote\debug\ccremote.ilk -f:\myapp\ccremote\ccremote\debug\ccremote.exe -f:\myapp\ccremote\ccremote\debug\ccremote.pdb -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.res -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\cl.command.1.tlog -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\cl.read.1.tlog -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\cl.write.1.tlog -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\link.command.1.tlog -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\link.read.1.tlog -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\link.write.1.tlog -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\rc.command.1.tlog -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\rc.read.1.tlog -f:\myapp\ccremote\ccremote\ccremote\debug\ccremote.tlog\rc.write.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.pch +g:\ccremote\ccremote\ccremote\ccremote\debug\vc141.pdb +g:\ccremote\ccremote\ccremote\ccremote\debug\vc141.idb +g:\ccremote\ccremote\ccremote\ccremote\debug\pch.obj +g:\ccremote\ccremote\ccremote\ccremote\debug\truecolortoolbar.obj +g:\ccremote\ccremote\ccremote\ccremote\debug\cpuusage.obj +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremotedlg.obj +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.obj +g:\ccremote\ccremote\ccremote\ccremote\debug\iocpserver.obj +g:\ccremote\ccremote\ccremote\ccremote\debug\buffer.obj +g:\ccremote\ccremote\ccremote\debug\ccremote.ilk +g:\ccremote\ccremote\ccremote\debug\ccremote.exe +g:\ccremote\ccremote\ccremote\debug\ccremote.pdb +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.res +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\cl.command.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\cl.read.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\cl.write.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\link.command.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\link.read.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\link.write.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\rc.command.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\rc.read.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\debug\ccremote.tlog\rc.write.1.tlog diff --git a/CcRemote/CcRemote/Debug/CcRemote.log b/CcRemote/CcRemote/Debug/CcRemote.log index dbc1b9c..21771c4 100644 --- a/CcRemote/CcRemote/Debug/CcRemote.log +++ b/CcRemote/CcRemote/Debug/CcRemote.log @@ -1,8 +1,18 @@  pch.cpp CcRemote.cpp CcRemoteDlg.cpp -f:\myapp\ccremote\ccremote\ccremote\ccremotedlg.cpp(220): warning C4244: “初始化”: 从“double”转换到“int”,可能丢失数据 -f:\myapp\ccremote\ccremote\ccremote\ccremotedlg.cpp(237): warning C4244: “初始化”: 从“double”转换到“int”,可能丢失数据 +g:\ccremote\ccremote\ccremote\ccremote\ccremotedlg.cpp(218): warning C4244: “初始化”: 从“double”转换到“int”,可能丢失数据 +g:\ccremote\ccremote\ccremote\ccremote\ccremotedlg.cpp(235): warning C4244: “初始化”: 从“double”转换到“int”,可能丢失数据 + CpuUsage.cpp TrueColorToolBar.cpp 正在生成代码... - CcRemote.vcxproj -> F:\myapp\CcRemote\CcRemote\Debug\CcRemote.exe + Buffer.cpp + IOCPServer.cpp +g:\ccremote\ccremote\ccremote\ccremote\include\iocpserver.cpp(129): warning C4996: 'WSASocketA': Use WSASocketW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings + g:\windows kits\10\include\10.0.17763.0\um\winsock2.h(3416): note: 参见“WSASocketA”的声明 +g:\ccremote\ccremote\ccremote\ccremote\include\iocpserver.cpp(715): warning C4996: 'inet_ntoa': Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings + g:\windows kits\10\include\10.0.17763.0\um\winsock2.h(1849): note: 参见“inet_ntoa”的声明 +g:\ccremote\ccremote\ccremote\ccremote\include\iocpserver.cpp(764): warning C4244: “初始化”: 从“double”转换到“unsigned long”,可能丢失数据 +g:\ccremote\ccremote\ccremote\ccremote\include\iocpserver.cpp(910): warning C4018: “>=”: 有符号/无符号不匹配 + 正在生成代码... + CcRemote.vcxproj -> G:\CcRemote\CcRemote\CcRemote\Debug\CcRemote.exe diff --git a/CcRemote/CcRemote/Debug/CcRemote.tlog/CcRemote.lastbuildstate b/CcRemote/CcRemote/Debug/CcRemote.tlog/CcRemote.lastbuildstate index c0e4c06..4f8bf97 100644 --- a/CcRemote/CcRemote/Debug/CcRemote.tlog/CcRemote.lastbuildstate +++ b/CcRemote/CcRemote/Debug/CcRemote.tlog/CcRemote.lastbuildstate @@ -1,2 +1,2 @@ #TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0 -Debug|Win32|F:\myapp\CcRemote\CcRemote\| +Debug|Win32|G:\CcRemote\CcRemote\CcRemote\| diff --git a/CcRemote/CcRemote/Release/CcRemote.Build.CppClean.log b/CcRemote/CcRemote/Release/CcRemote.Build.CppClean.log new file mode 100644 index 0000000..24d499f --- /dev/null +++ b/CcRemote/CcRemote/Release/CcRemote.Build.CppClean.log @@ -0,0 +1,24 @@ +g:\ccremote\ccremote\ccremote\release\ccremote.ipdb +g:\ccremote\ccremote\ccremote\release\ccremote.iobj +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.pch +g:\ccremote\ccremote\ccremote\ccremote\release\vc141.pdb +g:\ccremote\ccremote\ccremote\ccremote\release\pch.obj +g:\ccremote\ccremote\ccremote\ccremote\release\truecolortoolbar.obj +g:\ccremote\ccremote\ccremote\ccremote\release\cpuusage.obj +g:\ccremote\ccremote\ccremote\ccremote\release\ccremotedlg.obj +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.obj +g:\ccremote\ccremote\ccremote\ccremote\release\iocpserver.obj +g:\ccremote\ccremote\ccremote\ccremote\release\buffer.obj +g:\ccremote\ccremote\ccremote\release\ccremote.exe +g:\ccremote\ccremote\ccremote\release\ccremote.pdb +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.res +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\ccremote.write.1u.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\cl.command.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\cl.read.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\cl.write.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\link.command.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\link.read.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\link.write.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\rc.command.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\rc.read.1.tlog +g:\ccremote\ccremote\ccremote\ccremote\release\ccremote.tlog\rc.write.1.tlog diff --git a/CcRemote/CcRemote/Release/CcRemote.log b/CcRemote/CcRemote/Release/CcRemote.log new file mode 100644 index 0000000..8077f4f --- /dev/null +++ b/CcRemote/CcRemote/Release/CcRemote.log @@ -0,0 +1,23 @@ + pch.cpp + CcRemote.cpp + CcRemoteDlg.cpp +g:\ccremote\ccremote\ccremote\ccremote\ccremotedlg.cpp(146): warning C4996: 'gethostbyname': Use getaddrinfo() or GetAddrInfoW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings + g:\windows kits\10\include\10.0.17763.0\um\winsock2.h(2219): note: 参见“gethostbyname”的声明 +g:\ccremote\ccremote\ccremote\ccremote\ccremotedlg.cpp(151): warning C4996: 'inet_ntoa': Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings + g:\windows kits\10\include\10.0.17763.0\um\winsock2.h(1849): note: 参见“inet_ntoa”的声明 +g:\ccremote\ccremote\ccremote\ccremote\ccremotedlg.cpp(291): warning C4244: “初始化”: 从“double”转换到“int”,可能丢失数据 +g:\ccremote\ccremote\ccremote\ccremote\ccremotedlg.cpp(308): warning C4244: “初始化”: 从“double”转换到“int”,可能丢失数据 + CpuUsage.cpp + TrueColorToolBar.cpp + Buffer.cpp + IOCPServer.cpp +g:\ccremote\ccremote\ccremote\ccremote\include\iocpserver.cpp(129): warning C4996: 'WSASocketA': Use WSASocketW() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings + g:\windows kits\10\include\10.0.17763.0\um\winsock2.h(3416): note: 参见“WSASocketA”的声明 +g:\ccremote\ccremote\ccremote\ccremote\include\iocpserver.cpp(715): warning C4996: 'inet_ntoa': Use inet_ntop() or InetNtop() instead or define _WINSOCK_DEPRECATED_NO_WARNINGS to disable deprecated API warnings + g:\windows kits\10\include\10.0.17763.0\um\winsock2.h(1849): note: 参见“inet_ntoa”的声明 +g:\ccremote\ccremote\ccremote\ccremote\include\iocpserver.cpp(764): warning C4244: “初始化”: 从“double”转换到“unsigned long”,可能丢失数据 +g:\ccremote\ccremote\ccremote\ccremote\include\iocpserver.cpp(910): warning C4018: “>=”: 有符号/无符号不匹配 + 正在生成代码 + All 391 functions were compiled because no usable IPDB/IOBJ from previous compilation was found. + 已完成代码的生成 + CcRemote.vcxproj -> G:\CcRemote\CcRemote\CcRemote\Release\CcRemote.exe diff --git a/CcRemote/CcRemote/Release/CcRemote.res b/CcRemote/CcRemote/Release/CcRemote.res new file mode 100644 index 0000000..c8d7db2 Binary files /dev/null and b/CcRemote/CcRemote/Release/CcRemote.res differ diff --git a/CcRemote/CcRemote/Release/CcRemote.tlog/CcRemote.lastbuildstate b/CcRemote/CcRemote/Release/CcRemote.tlog/CcRemote.lastbuildstate new file mode 100644 index 0000000..cb3e57d --- /dev/null +++ b/CcRemote/CcRemote/Release/CcRemote.tlog/CcRemote.lastbuildstate @@ -0,0 +1,2 @@ +#TargetFrameworkVersion=v4.0:PlatformToolSet=v141:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=10.0.17763.0 +Release|Win32|G:\CcRemote\CcRemote\CcRemote\| diff --git a/CcRemote/CcRemote/include/Buffer.cpp b/CcRemote/CcRemote/include/Buffer.cpp new file mode 100644 index 0000000..f7c829a --- /dev/null +++ b/CcRemote/CcRemote/include/Buffer.cpp @@ -0,0 +1,524 @@ +// Buffer.cpp: implementation of the CBuffer class. +// +////////////////////////////////////////////////////////////////////// + +#include "..\pch.h" +#include "Buffer.h" +#include "Math.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CBuffer +// +// DESCRIPTION: Constructs the buffer with a default size +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +CBuffer::CBuffer() +{ + // Initial size + m_nSize = 0; + + m_pPtr = m_pBase = NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: ~CBuffer +// +// DESCRIPTION: Deallocates the buffer +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +CBuffer::~CBuffer() +{ + if (m_pBase) + VirtualFree(m_pBase,0,MEM_RELEASE); +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Write +// +// DESCRIPTION: Writes data into the buffer +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +BOOL CBuffer::Write(PBYTE pData, UINT nSize) +{ + ReAllocateBuffer(nSize + GetBufferLen()); + + CopyMemory(m_pPtr,pData,nSize); + + // Advance Pointer + m_pPtr+=nSize; + + return nSize; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Insert +// +// DESCRIPTION: Insert data into the buffer +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +BOOL CBuffer::Insert(PBYTE pData, UINT nSize) +{ + ReAllocateBuffer(nSize + GetBufferLen()); + + MoveMemory(m_pBase+nSize,m_pBase,GetMemSize() - nSize); + CopyMemory(m_pBase,pData,nSize); + + // Advance Pointer + m_pPtr+=nSize; + + return nSize; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Read +// +// DESCRIPTION: Reads data from the buffer and deletes what it reads +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +UINT CBuffer::Read(PBYTE pData, UINT nSize) +{ + // Trying to byte off more than ya can chew - eh? + if (nSize > GetMemSize()) + return 0; + + // all that we have + if (nSize > GetBufferLen()) + nSize = GetBufferLen(); + + + if (nSize) + { + // Copy over required amount and its not up to us + // to terminate the buffer - got that!!! + CopyMemory(pData,m_pBase,nSize); + + // Slide the buffer back - like sinking the data + MoveMemory(m_pBase,m_pBase+nSize,GetMemSize() - nSize); + + m_pPtr -= nSize; + } + + DeAllocateBuffer(GetBufferLen()); + + return nSize; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: GetMemSize +// +// DESCRIPTION: Returns the phyical memory allocated to the buffer +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +UINT CBuffer::GetMemSize() +{ + return m_nSize; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: GetBufferLen +// +// DESCRIPTION: Get the buffer 'data' length +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +UINT CBuffer::GetBufferLen() +{ + if (m_pBase == NULL) + return 0; + + int nSize = + m_pPtr - m_pBase; + return nSize; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: ReAllocateBuffer +// +// DESCRIPTION: ReAllocateBuffer the Buffer to the requested size +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +UINT CBuffer::ReAllocateBuffer(UINT nRequestedSize) +{ + if (nRequestedSize < GetMemSize()) + return 0; + + // Allocate new size + UINT nNewSize = (UINT) ceil(nRequestedSize / 1024.0) * 1024; + + // New Copy Data Over + PBYTE pNewBuffer = (PBYTE) VirtualAlloc(NULL,nNewSize,MEM_COMMIT,PAGE_READWRITE); + + UINT nBufferLen = GetBufferLen(); + CopyMemory(pNewBuffer,m_pBase,nBufferLen); + + if (m_pBase) + VirtualFree(m_pBase,0,MEM_RELEASE); + + + // Hand over the pointer + m_pBase = pNewBuffer; + + // Realign position pointer + m_pPtr = m_pBase + nBufferLen; + + m_nSize = nNewSize; + + return m_nSize; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: DeAllocateBuffer +// +// DESCRIPTION: DeAllocates the Buffer to the requested size +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +UINT CBuffer::DeAllocateBuffer(UINT nRequestedSize) +{ + if (nRequestedSize < GetBufferLen()) + return 0; + + // Allocate new size + UINT nNewSize = (UINT) ceil(nRequestedSize / 1024.0) * 1024; + + if (nNewSize < GetMemSize()) + return 0; + + // New Copy Data Over + PBYTE pNewBuffer = (PBYTE) VirtualAlloc(NULL,nNewSize,MEM_COMMIT,PAGE_READWRITE); + + UINT nBufferLen = GetBufferLen(); + CopyMemory(pNewBuffer,m_pBase,nBufferLen); + + VirtualFree(m_pBase,0,MEM_RELEASE); + + // Hand over the pointer + m_pBase = pNewBuffer; + + // Realign position pointer + m_pPtr = m_pBase + nBufferLen; + + m_nSize = nNewSize; + + return m_nSize; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Scan +// +// DESCRIPTION: Scans the buffer for a given byte sequence +// +// RETURNS: Logical offset +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +int CBuffer::Scan(PBYTE pScan,UINT nPos) +{ + if (nPos > GetBufferLen() ) + return -1; + + PBYTE pStr = (PBYTE) strstr((char*)(m_pBase+nPos),(char*)pScan); + + int nOffset = 0; + + if (pStr) + nOffset = (pStr - m_pBase) + strlen((char*)pScan); + + return nOffset; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: ClearBuffer +// +// DESCRIPTION: Clears/Resets the buffer +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +void CBuffer::ClearBuffer() +{ + // Force the buffer to be empty + m_pPtr = m_pBase; + + DeAllocateBuffer(1024); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Write +// +// DESCRIPTION: Writes a string a the end of the buffer +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +BOOL CBuffer::Write(CString& strData) +{ + int nSize = strData.GetLength(); + return Write((PBYTE) strData.GetBuffer(nSize), nSize); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Insert +// +// DESCRIPTION: Insert a string at the beginning of the buffer +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +BOOL CBuffer::Insert(CString& strData) +{ + int nSize = strData.GetLength(); + return Insert((PBYTE) strData.GetBuffer(nSize), nSize); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Copy +// +// DESCRIPTION: Copy from one buffer object to another... +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +void CBuffer::Copy(CBuffer& buffer) +{ + int nReSize = buffer.GetMemSize(); + int nSize = buffer.GetBufferLen(); + ClearBuffer(); + ReAllocateBuffer(nReSize); + + m_pPtr = m_pBase + nSize; + + CopyMemory(m_pBase,buffer.GetBuffer(),buffer.GetBufferLen()); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: GetBuffer +// +// DESCRIPTION: Returns a pointer to the physical memory determined by the offset +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +PBYTE CBuffer::GetBuffer(UINT nPos) +{ + return m_pBase+nPos; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: GetBuffer +// +// DESCRIPTION: Returns a pointer to the physical memory determined by the offset +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +/////////////////////////////////////////////////////////////////////////////// +void CBuffer::FileWrite(const CString& strFileName) +{ + CFile file; + + if (file.Open(strFileName, CFile::modeWrite | CFile::modeCreate)) + { + file.Write(m_pBase,GetBufferLen()); + file.Close(); + } +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Delete +// +// DESCRIPTION: Delete data from the buffer and deletes what it reads +// +// RETURNS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 270400 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +UINT CBuffer::Delete(UINT nSize) +{ + // Trying to byte off more than ya can chew - eh? + if (nSize > GetMemSize()) + return 0; + + // all that we have + if (nSize > GetBufferLen()) + nSize = GetBufferLen(); + + + if (nSize) + { + // Slide the buffer back - like sinking the data + MoveMemory(m_pBase,m_pBase+nSize,GetMemSize() - nSize); + + m_pPtr -= nSize; + } + + DeAllocateBuffer(GetBufferLen()); + + return nSize; +} \ No newline at end of file diff --git a/CcRemote/CcRemote/include/Buffer.h b/CcRemote/CcRemote/include/Buffer.h new file mode 100644 index 0000000..ff78e46 --- /dev/null +++ b/CcRemote/CcRemote/include/Buffer.h @@ -0,0 +1,49 @@ +// Buffer.h: interface for the CBuffer class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_BUFFER_H__829F6693_AC4D_11D2_8C37_00600877E420__INCLUDED_) +#define AFX_BUFFER_H__829F6693_AC4D_11D2_8C37_00600877E420__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CBuffer +{ +// Attributes +protected: + PBYTE m_pBase; + PBYTE m_pPtr; + UINT m_nSize; + + +// Methods +protected: + UINT ReAllocateBuffer(UINT nRequestedSize); + UINT DeAllocateBuffer(UINT nRequestedSize); + UINT GetMemSize(); +public: + void ClearBuffer(); + + UINT Delete(UINT nSize); + UINT Read(PBYTE pData, UINT nSize); + BOOL Write(PBYTE pData, UINT nSize); + BOOL Write(CString& strData); + UINT GetBufferLen(); + int Scan(PBYTE pScan,UINT nPos); + BOOL Insert(PBYTE pData, UINT nSize); + BOOL Insert(CString& strData); + + void Copy(CBuffer& buffer); + + PBYTE GetBuffer(UINT nPos=0); + + CBuffer(); + virtual ~CBuffer(); + + void FileWrite(const CString& strFileName); + +}; + +#endif // !defined(AFX_BUFFER_H__829F6693_AC4D_11D2_8C37_00600877E420__INCLUDED_) diff --git a/CcRemote/CcRemote/include/CpuUsage.cpp b/CcRemote/CcRemote/include/CpuUsage.cpp new file mode 100644 index 0000000..3cfefa7 --- /dev/null +++ b/CcRemote/CcRemote/include/CpuUsage.cpp @@ -0,0 +1,70 @@ +// CpuUsage.cpp: implementation of the CCpuUsage class. +// +////////////////////////////////////////////////////////////////////// + +#include "pch.h" +#include "CpuUsage.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CCpuUsage::CCpuUsage() +{ + m_hQuery = NULL; + m_pCounterStruct = NULL; + +} + +CCpuUsage::~CCpuUsage() +{ + + PdhCloseQuery(m_hQuery); + delete m_pCounterStruct; +} + + +BOOL CCpuUsage::Init() +{ + if (ERROR_SUCCESS != PdhOpenQuery(NULL, 1, &m_hQuery)) + return FALSE; + + m_pCounterStruct = (PPDHCOUNTERSTRUCT) new PDHCOUNTERSTRUCT; + + PDH_STATUS pdh_status = PdhAddCounter(m_hQuery, szCounterName, (DWORD) m_pCounterStruct, &(m_pCounterStruct->hCounter)); + if (ERROR_SUCCESS != pdh_status) + { + return FALSE; + } + + + + return TRUE; +} + + +int CCpuUsage::GetUsage() +{ + PDH_FMT_COUNTERVALUE pdhFormattedValue; + + PdhCollectQueryData(m_hQuery); + + if (ERROR_SUCCESS != PdhGetFormattedCounterValue( + m_pCounterStruct->hCounter, + PDH_FMT_LONG, + NULL, + &pdhFormattedValue )) + + + { + return 0; + } + + return pdhFormattedValue.longValue; +} \ No newline at end of file diff --git a/CcRemote/CcRemote/include/CpuUsage.h b/CcRemote/CcRemote/include/CpuUsage.h new file mode 100644 index 0000000..9f57ac8 --- /dev/null +++ b/CcRemote/CcRemote/include/CpuUsage.h @@ -0,0 +1,47 @@ +// CpuUsage.h: interface for the CCpuUsage class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CPUUSAGE_H__60CF4F03_9F01_41E8_A9FB_51F065D5F3C2__INCLUDED_) +#define AFX_CPUUSAGE_H__60CF4F03_9F01_41E8_A9FB_51F065D5F3C2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include +#include + +#pragma comment(lib,"PDH.lib") + + +#define MAX_RAW_VALUES 20 + +const char szCounterName[] = "\\Processor(_Total)\\% Processor Time"; + +typedef struct _tag_PDHCounterStruct { + HCOUNTER hCounter; // Handle to the counter - given to use by PDH Library + int nNextIndex; // element to get the next raw value + int nOldestIndex; // element containing the oldes raw value + int nRawCount; // number of elements containing raw values + PDH_RAW_COUNTER a_RawValue[MAX_RAW_VALUES]; // Ring buffer to contain raw values +} PDHCOUNTERSTRUCT, *PPDHCOUNTERSTRUCT; + + +class CCpuUsage +{ +public: + CCpuUsage(); + virtual ~CCpuUsage(); + BOOL Init(); + int GetUsage(); + +protected: + + PPDHCOUNTERSTRUCT m_pCounterStruct; + HQUERY m_hQuery; + + +}; + +#endif // !defined(AFX_CPUUSAGE_H__60CF4F03_9F01_41E8_A9FB_51F065D5F3C2__INCLUDED_) diff --git a/CcRemote/CcRemote/include/IOCPServer.cpp b/CcRemote/CcRemote/include/IOCPServer.cpp new file mode 100644 index 0000000..f199cac --- /dev/null +++ b/CcRemote/CcRemote/include/IOCPServer.cpp @@ -0,0 +1,1305 @@ +// IOCPServer.cpp: implementation of the CIOCPServer class. +// +////////////////////////////////////////////////////////////////////// + +#include"..\pch.h" +#include "IOCPServer.h" +#include "..\..\..\common\zlib\zlib.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[]=__FILE__; +#define new DEBUG_NEW +#endif + +// Change at your Own Peril + +// 'G' 'h' '0' 's' 't' | PacketLen | UnZipLen +#define HDR_SIZE 13 +#define FLAG_SIZE 5 +#define HUERISTIC_VALUE 2 +CRITICAL_SECTION CIOCPServer::m_cs; + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::CIOCPServer +// +// DESCRIPTION: C'tor initializes Winsock2 and miscelleanous events etc. +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// + +//lang2.1_4 +CIOCPServer::CIOCPServer() //򵥷CIOCPServer ׽ݴ +{ + TRACE("CIOCPServer=%p\n",this); + + // + WSADATA wsaData; + WSAStartup(MAKEWORD(2,2), &wsaData); //ʼ׽ + + InitializeCriticalSection(&m_cs); + + m_hThread = NULL; + m_hKillEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + m_socListen = NULL; + + m_bTimeToKill = false; + m_bDisconnectAll = false; + + m_hEvent = NULL; + m_hCompletionPort= NULL; + + m_bInit = false; + m_nCurrentThreads = 0; + m_nBusyThreads = 0; + + m_nSendKbps = 0; + m_nRecvKbps = 0; + + m_nMaxConnections = 10000; + m_nKeepLiveTime = 1000 * 60 * 3; // ̽һ + // Packet Flag; + BYTE bPacketFlag[] = {'G', 'h', '0', 's', 't'}; //ݷ͵ı ͬͻַһ + memcpy(m_bPacketFlag, bPacketFlag, sizeof(bPacketFlag)); +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::CIOCPServer +// +// DESCRIPTION: Tidy up +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +CIOCPServer::~CIOCPServer() +{ + try + { + Shutdown(); + WSACleanup(); + }catch(...){} +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: Init +// +// DESCRIPTION: Starts listener into motion +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +//lang2.1_5 ʼ˿ +bool CIOCPServer::Initialize(NOTIFYPROC pNotifyProc, CMainFrame* pFrame, int nMaxConnections, int nPort) +{ + m_pNotifyProc = pNotifyProc; + m_pFrame = pFrame; + m_nMaxConnections = nMaxConnections; + m_socListen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); + + //ʼ ׽ + if (m_socListen == INVALID_SOCKET) + { + TRACE(_T("Could not create listen socket %ld\n"),WSAGetLastError()); + return false; + } + + // Event for handling Network IO + m_hEvent = WSACreateEvent(); + + if (m_hEvent == WSA_INVALID_EVENT) + { + TRACE(_T("WSACreateEvent() error %ld\n"),WSAGetLastError()); + closesocket(m_socListen); + return false; + } + + // The listener is ONLY interested in FD_ACCEPT + // That is when a client connects to or IP/Port + // Request async notification + int nRet = WSAEventSelect(m_socListen, + m_hEvent, + FD_ACCEPT); + + if (nRet == SOCKET_ERROR) + { + TRACE(_T("WSAAsyncSelect() error %ld\n"),WSAGetLastError()); + closesocket(m_socListen); + return false; + } + + SOCKADDR_IN saServer; + + + // Listen on our designated Port# + saServer.sin_port = htons(nPort); + + // Fill in the rest of the address structure + saServer.sin_family = AF_INET; + saServer.sin_addr.s_addr = INADDR_ANY; + + // bind our name to the socket + nRet = bind(m_socListen, + (LPSOCKADDR)&saServer, + sizeof(struct sockaddr)); + + if (nRet == SOCKET_ERROR) + { + TRACE(_T("bind() error %ld\n"),WSAGetLastError()); + closesocket(m_socListen); + return false; + } + + // Set the socket to listen + nRet = listen(m_socListen, SOMAXCONN); + if (nRet == SOCKET_ERROR) + { + TRACE(_T("listen() error %ld\n"),WSAGetLastError()); + closesocket(m_socListen); + return false; + } + + + //////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////// + UINT dwThreadId = 0; + //߳ ListenThreadProc + m_hThread = + (HANDLE)_beginthreadex(NULL, // Security + 0, // Stack size - use default + ListenThreadProc, // Thread fn entry point + (void*) this, + 0, // Init flag + &dwThreadId); // Thread address + + if (m_hThread != INVALID_HANDLE_VALUE) + { + InitializeIOCP(); + m_bInit = true; + return true; + } + + return false; +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::ListenThreadProc +// +// DESCRIPTION: Listens for incoming clients +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +//lang2.1_6 +unsigned CIOCPServer::ListenThreadProc(LPVOID lParam) //߳ +{ + CIOCPServer* pThis = reinterpret_cast(lParam); + + WSANETWORKEVENTS events; + + while(1) + { + // + // Wait for something to happen + // + if (WaitForSingleObject(pThis->m_hKillEvent, 100) == WAIT_OBJECT_0) + break; + + DWORD dwRet; + dwRet = WSAWaitForMultipleEvents(1, + &pThis->m_hEvent, + FALSE, + 100, + FALSE); + + if (dwRet == WSA_WAIT_TIMEOUT) + continue; + + // + // Figure out what happened + // + int nRet = WSAEnumNetworkEvents(pThis->m_socListen, + pThis->m_hEvent, + &events); + + if (nRet == SOCKET_ERROR) + { + TRACE(_T("WSAEnumNetworkEvents error %ld\n"),WSAGetLastError()); + break; + } + + // Handle Network events // + // ACCEPT + if (events.lNetworkEvents & FD_ACCEPT) + { + if (events.iErrorCode[FD_ACCEPT_BIT] == 0) + pThis->OnAccept(); //Ӿ͵ 뿴 + else + { + TRACE(_T("Unknown network event error %ld\n"),WSAGetLastError()); + break; + } + + } + + } // while.... + + return 0; // Normal Thread Exit Code... +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::OnAccept +// +// DESCRIPTION: Listens for incoming clients +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// Ulf Hedlund 09072001 Changes for OVERLAPPEDPLUS +//////////////////////////////////////////////////////////////////////////////// + +//lang2.1_7 +void CIOCPServer::OnAccept() +{ + + SOCKADDR_IN SockAddr; + SOCKET clientSocket; + + int nRet; + int nLen; + + if (m_bTimeToKill || m_bDisconnectAll) + return; + + // + // accept the new socket descriptor + // + nLen = sizeof(SOCKADDR_IN); + clientSocket = accept(m_socListen, + (LPSOCKADDR)&SockAddr, + &nLen); + + if (clientSocket == SOCKET_ERROR) + { + nRet = WSAGetLastError(); + if (nRet != WSAEWOULDBLOCK) + { + // + // Just log the error and return + // + TRACE(_T("accept() error\n"),WSAGetLastError()); + return; + } + } + + // Create the Client context to be associted with the completion port + ClientContext* pContext = AllocateContext(); + // AllocateContext fail + if (pContext == NULL) + return; + + pContext->m_Socket = clientSocket; + + // Fix up In Buffer + pContext->m_wsaInBuffer.buf = (char*)pContext->m_byInBuffer; + pContext->m_wsaInBuffer.len = sizeof(pContext->m_byInBuffer); + + // Associate the new socket with a completion port. + if (!AssociateSocketWithCompletionPort(clientSocket, m_hCompletionPort, (DWORD) pContext)) + { + delete pContext; + pContext = NULL; + + closesocket( clientSocket ); + closesocket( m_socListen ); + return; + } + + // رnagle㷨,ӰܣΪʱƶҪͺܶСݰ,ҪϷ + // ݲرգʵ֪кܴӰ + const char chOpt = 1; + +// int nErr = setsockopt(pContext->m_Socket, IPPROTO_TCP, TCP_NODELAY, &chOpt, sizeof(char)); +// if (nErr == -1) +// { +// TRACE(_T("setsockopt() error\n"),WSAGetLastError()); +// return; +// } + + // Set KeepAlive + if (setsockopt(pContext->m_Socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&chOpt, sizeof(chOpt)) != 0) + { + TRACE(_T("setsockopt() error\n"), WSAGetLastError()); + } + + // óʱϸϢ + tcp_keepalive klive; + klive.onoff = 1; // ñ + klive.keepalivetime = m_nKeepLiveTime; + klive.keepaliveinterval = 1000 * 10; // ԼΪ10 Resend if No-Reply + WSAIoctl + ( + pContext->m_Socket, + SIO_KEEPALIVE_VALS, + &klive, + sizeof(tcp_keepalive), + NULL, + 0, + (unsigned long *)&chOpt, + 0, + NULL + ); + + CLock cs(m_cs, "OnAccept" ); + // Hold a reference to the context + m_listContexts.AddTail(pContext); + + + // Trigger first IO Completion Request + // Otherwise the Worker thread will remain blocked waiting for GetQueuedCompletionStatus... + // The first message that gets queued up is ClientIoInitializing - see ThreadPoolFunc and + // IO_MESSAGE_HANDLER + + + OVERLAPPEDPLUS *pOverlap = new OVERLAPPEDPLUS(IOInitialize); + + BOOL bSuccess = PostQueuedCompletionStatus(m_hCompletionPort, 0, (DWORD) pContext, &pOverlap->m_ol); + + if ( (!bSuccess && GetLastError( ) != ERROR_IO_PENDING)) + { + RemoveStaleClient(pContext,TRUE); + return; + } + + m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_CLIENT_CONNECT); //ص 鿴Initialize ʹ + + // Post to WSARecv Next + PostRecv(pContext); +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::InitializeIOCP +// +// DESCRIPTION: Create a dummy socket and associate a completion port with it. +// once completion port is create we can dicard the socket +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +bool CIOCPServer::InitializeIOCP(void) +{ + + SOCKET s; + DWORD i; + UINT nThreadID; + SYSTEM_INFO systemInfo; + + // + // First open a temporary socket that we will use to create the + // completion port. In NT 3.51 it will not be necessary to specify + // the FileHandle parameter of CreateIoCompletionPort()--it will + // be legal to specify FileHandle as NULL. However, for NT 3.5 + // we need an overlapped file handle. + // + + s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); + if ( s == INVALID_SOCKET ) + return false; + + // Create the completion port that will be used by all the worker + // threads. + m_hCompletionPort = CreateIoCompletionPort( (HANDLE)s, NULL, 0, 0 ); + if ( m_hCompletionPort == NULL ) + { + closesocket( s ); + return false; + } + + // Close the socket, we don't need it any longer. + closesocket( s ); + + // Determine how many processors are on the system. + GetSystemInfo( &systemInfo ); + + m_nThreadPoolMin = systemInfo.dwNumberOfProcessors * HUERISTIC_VALUE; + m_nThreadPoolMax = m_nThreadPoolMin; + m_nCPULoThreshold = 10; + m_nCPUHiThreshold = 75; + + m_cpu.Init(); + + + // We use two worker threads for eachprocessor on the system--this is choosen as a good balance + // that ensures that there are a sufficient number of threads available to get useful work done + // but not too many that context switches consume significant overhead. + UINT nWorkerCnt = systemInfo.dwNumberOfProcessors * HUERISTIC_VALUE; + + // We need to save the Handles for Later Termination... + HANDLE hWorker; + m_nWorkerCnt = 0; + + for ( i = 0; i < nWorkerCnt; i++ ) + { + hWorker = (HANDLE)_beginthreadex(NULL, // Security + 0, // Stack size - use default + ThreadPoolFunc, // Thread fn entry point + (void*) this, // Param for thread + 0, // Init flag + &nThreadID); // Thread address + + + if (hWorker == NULL ) + { + CloseHandle( m_hCompletionPort ); + return false; + } + + m_nWorkerCnt++; + + CloseHandle(hWorker); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::ThreadPoolFunc +// +// DESCRIPTION: This is the main worker routine for the worker threads. +// Worker threads wait on a completion port for I/O to complete. +// When it completes, the worker thread processes the I/O, then either pends +// new I/O or closes the client's connection. When the service shuts +// down, other code closes the completion port which causes +// GetQueuedCompletionStatus() to wake up and the worker thread then +// exits. +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// Ulf Hedlund 09062001 Changes for OVERLAPPEDPLUS +//////////////////////////////////////////////////////////////////////////////// +unsigned CIOCPServer::ThreadPoolFunc (LPVOID thisContext) +{ + // Get back our pointer to the class + ULONG ulFlags = MSG_PARTIAL; + CIOCPServer* pThis = reinterpret_cast(thisContext); + ASSERT(pThis); + + HANDLE hCompletionPort = pThis->m_hCompletionPort; + + DWORD dwIoSize; + LPOVERLAPPED lpOverlapped; + ClientContext* lpClientContext; + OVERLAPPEDPLUS* pOverlapPlus; + bool bError; + bool bEnterRead; + + InterlockedIncrement(&pThis->m_nCurrentThreads); + InterlockedIncrement(&pThis->m_nBusyThreads); + + // + // Loop round and round servicing I/O completions. + // + + for (BOOL bStayInPool = TRUE; bStayInPool && pThis->m_bTimeToKill == false; ) + { + pOverlapPlus = NULL; + lpClientContext = NULL; + bError = false; + bEnterRead = false; + // Thread is Block waiting for IO completion + InterlockedDecrement(&pThis->m_nBusyThreads); + + + // Get a completed IO request. + BOOL bIORet = GetQueuedCompletionStatus( + hCompletionPort, + &dwIoSize, + (LPDWORD) &lpClientContext, + &lpOverlapped, INFINITE); + + DWORD dwIOError = GetLastError(); + pOverlapPlus = CONTAINING_RECORD(lpOverlapped, OVERLAPPEDPLUS, m_ol); + + + int nBusyThreads = InterlockedIncrement(&pThis->m_nBusyThreads); + + if (!bIORet && dwIOError != WAIT_TIMEOUT ) + { + if (lpClientContext && pThis->m_bTimeToKill == false) + { + pThis->RemoveStaleClient(lpClientContext, FALSE); + } + continue; + + // anyway, this was an error and we should exit + bError = true; + } + + if (!bError) + { + + // Allocate another thread to the thread Pool? + if (nBusyThreads == pThis->m_nCurrentThreads) + { + if (nBusyThreads < pThis->m_nThreadPoolMax) + { + if (pThis->m_cpu.GetUsage() > pThis->m_nCPUHiThreshold) + { + UINT nThreadID = -1; + +// HANDLE hThread = (HANDLE)_beginthreadex(NULL, // Security +// 0, // Stack size - use default +// ThreadPoolFunc, // Thread fn entry point +/// (void*) pThis, +// 0, // Init flag +// &nThreadID); // Thread address + +// CloseHandle(hThread); + } + } + } + + + // Thread timed out - IDLE? + if (!bIORet && dwIOError == WAIT_TIMEOUT) + { + if (lpClientContext == NULL) + { + if (pThis->m_cpu.GetUsage() < pThis->m_nCPULoThreshold) + { + // Thread has no outstanding IO - Server hasn't much to do so die + if (pThis->m_nCurrentThreads > pThis->m_nThreadPoolMin) + bStayInPool = FALSE; + } + + bError = true; + } + } + } +////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////// + if (!bError) + { + if(bIORet && NULL != pOverlapPlus && NULL != lpClientContext) + { + try + { + pThis->ProcessIOMessage(pOverlapPlus->m_ioType, lpClientContext, dwIoSize); + } + catch (...) {} + } + } + + if(pOverlapPlus) + delete pOverlapPlus; // from previous call + } + + InterlockedDecrement(&pThis->m_nWorkerCnt); + + InterlockedDecrement(&pThis->m_nCurrentThreads); + InterlockedDecrement(&pThis->m_nBusyThreads); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::Stop +// +// DESCRIPTION: Signal the listener to quit his thread +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +void CIOCPServer::Stop() +{ + ::SetEvent(m_hKillEvent); + WaitForSingleObject(m_hThread, INFINITE); + CloseHandle(m_hThread); + CloseHandle(m_hKillEvent); +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::GetHostName +// +// DESCRIPTION: Get the host name of the connect client +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +CString CIOCPServer::GetHostName(SOCKET socket) +{ + sockaddr_in sockAddr; + memset(&sockAddr, 0, sizeof(sockAddr)); + + int nSockAddrLen = sizeof(sockAddr); + + BOOL bResult = getpeername(socket,(SOCKADDR*)&sockAddr, &nSockAddrLen); + + return bResult != INVALID_SOCKET ? inet_ntoa(sockAddr.sin_addr) : ""; +} + + +void CIOCPServer::PostRecv(ClientContext* pContext) +{ + // issue a read request + OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IORead); + ULONG ulFlags = MSG_PARTIAL; + DWORD dwNumberOfBytesRecvd; + UINT nRetVal = WSARecv(pContext->m_Socket, + &pContext->m_wsaInBuffer, + 1, + &dwNumberOfBytesRecvd, + &ulFlags, + &pOverlap->m_ol, + NULL); + + if ( nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING) + { + RemoveStaleClient(pContext, FALSE); + } +} +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::Send +// +// DESCRIPTION: Posts a Write + Data to IO CompletionPort for transfer +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// Ulf Hedlund 09062001 Changes for OVERLAPPEDPLUS +//////////////////////////////////////////////////////////////////////////////// +void CIOCPServer::Send(ClientContext* pContext, LPBYTE lpData, UINT nSize) +{ + if (pContext == NULL) + return; + + try + { + if (nSize > 0) + { + // Compress data + unsigned long destLen = (double)nSize * 1.001 + 12; + LPBYTE pDest = new BYTE[destLen]; + int nRet = compress(pDest, &destLen, lpData, nSize); + + if (nRet != Z_OK) + { + delete [] pDest; + return; + } + + ////////////////////////////////////////////////////////////////////////// + LONG nBufLen = destLen + HDR_SIZE; + // 5 bytes packet flag + pContext->m_WriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag)); + // 4 byte header [Size of Entire Packet] + pContext->m_WriteBuffer.Write((PBYTE) &nBufLen, sizeof(nBufLen)); + // 4 byte header [Size of UnCompress Entire Packet] + pContext->m_WriteBuffer.Write((PBYTE) &nSize, sizeof(nSize)); + // Write Data + pContext->m_WriteBuffer.Write(pDest, destLen); + delete [] pDest; + + // ٱ, Ϊпm_ResendWriteBufferڷ,Բֱд + LPBYTE lpResendWriteBuffer = new BYTE[nSize]; + CopyMemory(lpResendWriteBuffer, lpData, nSize); + pContext->m_ResendWriteBuffer.ClearBuffer(); + pContext->m_ResendWriteBuffer.Write(lpResendWriteBuffer, nSize); // ݷ͵ + delete [] lpResendWriteBuffer; + } + else // Ҫط + { + pContext->m_WriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag)); + pContext->m_ResendWriteBuffer.ClearBuffer(); + pContext->m_ResendWriteBuffer.Write(m_bPacketFlag, sizeof(m_bPacketFlag)); // ݷ͵ + } + // Wait for Data Ready signal to become available + WaitForSingleObject(pContext->m_hWriteComplete, INFINITE); + + // Prepare Packet + // pContext->m_wsaOutBuffer.buf = (CHAR*) new BYTE[nSize]; + // pContext->m_wsaOutBuffer.len = pContext->m_WriteBuffer.GetBufferLen(); + + OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IOWrite); + PostQueuedCompletionStatus(m_hCompletionPort, 0, (DWORD) pContext, &pOverlap->m_ol); + + pContext->m_nMsgOut++; + }catch(...){} +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CClientListener::OnClientInitializing +// +// DESCRIPTION: Called when client is initailizing +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// Ulf Hedlund 09062001 Changes for OVERLAPPEDPLUS +//////////////////////////////////////////////////////////////////////////////// +bool CIOCPServer::OnClientInitializing(ClientContext* pContext, DWORD dwIoSize) +{ + // We are not actually doing anything here, but we could for instance make + // a call to Send() to send a greeting message or something + + return true; // make sure to issue a read after this +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::OnClientReading +// +// DESCRIPTION: Called when client is reading +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// Ulf Hedlund 09062001 Changes for OVERLAPPEDPLUS +//////////////////////////////////////////////////////////////////////////////// +bool CIOCPServer::OnClientReading(ClientContext* pContext, DWORD dwIoSize) +{ + CLock cs(CIOCPServer::m_cs, "OnClientReading"); + try + { + ////////////////////////////////////////////////////////////////////////// + static DWORD nLastTick = GetTickCount(); + static DWORD nBytes = 0; + nBytes += dwIoSize; + + if (GetTickCount() - nLastTick >= 1000) + { + nLastTick = GetTickCount(); + InterlockedExchange((LPLONG)&(m_nRecvKbps), nBytes); + nBytes = 0; + } + + ////////////////////////////////////////////////////////////////////////// + + if (dwIoSize == 0) + { + RemoveStaleClient(pContext, FALSE); + return false; + } + + if (dwIoSize == FLAG_SIZE && memcmp(pContext->m_byInBuffer, m_bPacketFlag, FLAG_SIZE) == 0) + { + // · + Send(pContext, pContext->m_ResendWriteBuffer.GetBuffer(), pContext->m_ResendWriteBuffer.GetBufferLen()); + // Ͷһ + PostRecv(pContext); + return true; + } + + // Add the message to out message + // Dont forget there could be a partial, 1, 1 or more + partial mesages + pContext->m_CompressionBuffer.Write(pContext->m_byInBuffer,dwIoSize); + + m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_RECEIVE); + + + // Check real Data + while (pContext->m_CompressionBuffer.GetBufferLen() > HDR_SIZE) + { + BYTE bPacketFlag[FLAG_SIZE]; + CopyMemory(bPacketFlag, pContext->m_CompressionBuffer.GetBuffer(), sizeof(bPacketFlag)); + + if (memcmp(m_bPacketFlag, bPacketFlag, sizeof(m_bPacketFlag)) != 0) + throw "bad buffer"; + + int nSize = 0; + CopyMemory(&nSize, pContext->m_CompressionBuffer.GetBuffer(FLAG_SIZE), sizeof(int)); + + // Update Process Variable + pContext->m_nTransferProgress = pContext->m_CompressionBuffer.GetBufferLen() * 100 / nSize; + + if (nSize && (pContext->m_CompressionBuffer.GetBufferLen()) >= nSize) + { + int nUnCompressLength = 0; + // Read off header + pContext->m_CompressionBuffer.Read((PBYTE) bPacketFlag, sizeof(bPacketFlag)); + + pContext->m_CompressionBuffer.Read((PBYTE) &nSize, sizeof(int)); + pContext->m_CompressionBuffer.Read((PBYTE) &nUnCompressLength, sizeof(int)); + + //////////////////////////////////////////////////////// + //////////////////////////////////////////////////////// + // SO you would process your data here + // + // I'm just going to post message so we can see the data + int nCompressLength = nSize - HDR_SIZE; + PBYTE pData = new BYTE[nCompressLength]; + PBYTE pDeCompressionData = new BYTE[nUnCompressLength]; + + if (pData == NULL || pDeCompressionData == NULL) + throw "bad Allocate"; + + pContext->m_CompressionBuffer.Read(pData, nCompressLength); + + ////////////////////////////////////////////////////////////////////////// + unsigned long destLen = nUnCompressLength; + int nRet = uncompress(pDeCompressionData, &destLen, pData, nCompressLength); + ////////////////////////////////////////////////////////////////////////// + if (nRet == Z_OK) + { + pContext->m_DeCompressionBuffer.ClearBuffer(); + pContext->m_DeCompressionBuffer.Write(pDeCompressionData, destLen); + m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_RECEIVE_COMPLETE); + } + else + { + throw "bad buffer"; + } + + delete [] pData; + delete [] pDeCompressionData; + pContext->m_nMsgIn++; + } + else + break; + } + // Post to WSARecv Next + PostRecv(pContext); + }catch(...) + { + pContext->m_CompressionBuffer.ClearBuffer(); + // Ҫطͷ0, ںԶ־ + Send(pContext, NULL, 0); + PostRecv(pContext); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::OnClientWriting +// +// DESCRIPTION: Called when client is writing +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// Ulf Hedlund 09062001 Changes for OVERLAPPEDPLUS +//////////////////////////////////////////////////////////////////////////////// +bool CIOCPServer::OnClientWriting(ClientContext* pContext, DWORD dwIoSize) +{ + try + { + ////////////////////////////////////////////////////////////////////////// + static DWORD nLastTick = GetTickCount(); + static DWORD nBytes = 0; + + nBytes += dwIoSize; + + if (GetTickCount() - nLastTick >= 1000) + { + nLastTick = GetTickCount(); + InterlockedExchange((LPLONG)&(m_nSendKbps), nBytes); + nBytes = 0; + } + ////////////////////////////////////////////////////////////////////////// + + ULONG ulFlags = MSG_PARTIAL; + + // Finished writing - tidy up + pContext->m_WriteBuffer.Delete(dwIoSize); + if (pContext->m_WriteBuffer.GetBufferLen() == 0) + { + pContext->m_WriteBuffer.ClearBuffer(); + // Write complete + SetEvent(pContext->m_hWriteComplete); + return true; // issue new read after this one + } + else + { + OVERLAPPEDPLUS * pOverlap = new OVERLAPPEDPLUS(IOWrite); + + m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_TRANSMIT); + + + pContext->m_wsaOutBuffer.buf = (char*) pContext->m_WriteBuffer.GetBuffer(); + pContext->m_wsaOutBuffer.len = pContext->m_WriteBuffer.GetBufferLen(); + + int nRetVal = WSASend(pContext->m_Socket, + &pContext->m_wsaOutBuffer, + 1, + &pContext->m_wsaOutBuffer.len, + ulFlags, + &pOverlap->m_ol, + NULL); + + + if ( nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING ) + { + RemoveStaleClient( pContext, FALSE ); + } + + } + }catch(...){} + return false; // issue new read after this one +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::CloseCompletionPort +// +// DESCRIPTION: Close down the IO Complete Port, queue and associated client context structs +// which in turn will close the sockets... +// +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +void CIOCPServer::CloseCompletionPort() +{ + + while (m_nWorkerCnt) + { + PostQueuedCompletionStatus(m_hCompletionPort, 0, (DWORD) NULL, NULL); + Sleep(100); + } + + // Close the CompletionPort and stop any more requests + CloseHandle(m_hCompletionPort); + + ClientContext* pContext = NULL; + + do + { + POSITION pos = m_listContexts.GetHeadPosition(); + if (pos) + { + pContext = m_listContexts.GetNext(pos); + RemoveStaleClient(pContext, FALSE); + } + } + while (!m_listContexts.IsEmpty()); + + m_listContexts.RemoveAll(); + +} + + +BOOL CIOCPServer::AssociateSocketWithCompletionPort(SOCKET socket, HANDLE hCompletionPort, DWORD dwCompletionKey) +{ + HANDLE h = CreateIoCompletionPort((HANDLE) socket, hCompletionPort, dwCompletionKey, 0); + return h == hCompletionPort; +} + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::RemoveStaleClient +// +// DESCRIPTION: Client has died on us, close socket and remove context from our list +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +void CIOCPServer::RemoveStaleClient(ClientContext* pContext, BOOL bGraceful) +{ + CLock cs(m_cs, "RemoveStaleClient"); + + TRACE("CIOCPServer::RemoveStaleClient\n"); + + LINGER lingerStruct; + + + // + // If we're supposed to abort the connection, set the linger value + // on the socket to 0. + // + + if ( !bGraceful ) + { + + lingerStruct.l_onoff = 1; + lingerStruct.l_linger = 0; + setsockopt( pContext->m_Socket, SOL_SOCKET, SO_LINGER, + (char *)&lingerStruct, sizeof(lingerStruct) ); + } + + + + // + // Free context structures + if (m_listContexts.Find(pContext)) + { + + // + // Now close the socket handle. This will do an abortive or graceful close, as requested. + CancelIo((HANDLE) pContext->m_Socket); + + closesocket( pContext->m_Socket ); + pContext->m_Socket = INVALID_SOCKET; + + while (!HasOverlappedIoCompleted((LPOVERLAPPED)pContext)) + Sleep(0); + + m_pNotifyProc((LPVOID) m_pFrame, pContext, NC_CLIENT_DISCONNECT); + + MoveToFreePool(pContext); + + } +} + + +void CIOCPServer::Shutdown() +{ + if (m_bInit == false) + return; + + m_bInit = false; + m_bTimeToKill = true; + + // Stop the listener + Stop(); + + + closesocket(m_socListen); + WSACloseEvent(m_hEvent); + + + CloseCompletionPort(); + + DeleteCriticalSection(&m_cs); + + while (!m_listFreePool.IsEmpty()) + delete m_listFreePool.RemoveTail(); + +} + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::MoveToFreePool +// +// DESCRIPTION: Checks free pool otherwise allocates a context +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +void CIOCPServer::MoveToFreePool(ClientContext *pContext) +{ + CLock cs(m_cs, "MoveToFreePool"); + // Free context structures + POSITION pos = m_listContexts.Find(pContext); + if (pos) + { + pContext->m_CompressionBuffer.ClearBuffer(); + pContext->m_WriteBuffer.ClearBuffer(); + pContext->m_DeCompressionBuffer.ClearBuffer(); + pContext->m_ResendWriteBuffer.ClearBuffer(); + m_listFreePool.AddTail(pContext); + m_listContexts.RemoveAt(pos); + } +} + + + +//////////////////////////////////////////////////////////////////////////////// +// +// FUNCTION: CIOCPServer::MoveToFreePool +// +// DESCRIPTION: Moves an 'used/stale' Context to the free pool for reuse +// +// INPUTS: +// +// NOTES: +// +// MODIFICATIONS: +// +// Name Date Version Comments +// N T ALMOND 06042001 1.0 Origin +// +//////////////////////////////////////////////////////////////////////////////// +ClientContext* CIOCPServer::AllocateContext() +{ + ClientContext* pContext = NULL; + + CLock cs(CIOCPServer::m_cs, "AllocateContext"); + + if (!m_listFreePool.IsEmpty()) + { + pContext = m_listFreePool.RemoveHead(); + } + else + { + pContext = new ClientContext; + } + + ASSERT(pContext); + + if (pContext != NULL) + { + + ZeroMemory(pContext, sizeof(ClientContext)); + pContext->m_bIsMainSocket = false; + memset(pContext->m_Dialog, 0, sizeof(pContext->m_Dialog)); + } + return pContext; +} + + +void CIOCPServer::ResetConnection(ClientContext* pContext) +{ + + CString strHost; + ClientContext* pCompContext = NULL; + + CLock cs(CIOCPServer::m_cs, "ResetConnection"); + + POSITION pos = m_listContexts.GetHeadPosition(); + while (pos) + { + pCompContext = m_listContexts.GetNext(pos); + if (pCompContext == pContext) + { + RemoveStaleClient(pContext, TRUE); + break; + } + } +} + +void CIOCPServer::DisconnectAll() +{ + m_bDisconnectAll = true; + CString strHost; + ClientContext* pContext = NULL; + + CLock cs(CIOCPServer::m_cs, "DisconnectAll"); + + POSITION pos = m_listContexts.GetHeadPosition(); + while (pos) + { + pContext = m_listContexts.GetNext(pos); + RemoveStaleClient(pContext, TRUE); + } + m_bDisconnectAll = false; + +} + +bool CIOCPServer::IsRunning() +{ + return m_bInit; +} diff --git a/CcRemote/CcRemote/include/IOCPServer.h b/CcRemote/CcRemote/include/IOCPServer.h new file mode 100644 index 0000000..1d72d13 --- /dev/null +++ b/CcRemote/CcRemote/include/IOCPServer.h @@ -0,0 +1,214 @@ +// IOCPServer.h: interface for the CIOCPServer class. +// +////////////////////////////////////////////////////////////////////// +#include "..\pch.h" +#if !defined(AFX_IOCPSERVER_H__75B80E90_FD25_4FFB_B273_0090AA43BBDF__INCLUDED_) +#define AFX_IOCPSERVER_H__75B80E90_FD25_4FFB_B273_0090AA43BBDF__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include +#include +#pragma comment(lib,"ws2_32.lib") +#include "Buffer.h" +#include "CpuUsage.h" + + +#include + +#include + + + +//////////////////////////////////////////////////////////////////// +#define NC_CLIENT_CONNECT 0x0001 +#define NC_CLIENT_DISCONNECT 0x0002 +#define NC_TRANSMIT 0x0003 +#define NC_RECEIVE 0x0004 +#define NC_RECEIVE_COMPLETE 0x0005 // + +class CLock +{ +public: + CLock(CRITICAL_SECTION& cs, const CString& strFunc) + { + m_strFunc = strFunc; + m_pcs = &cs; + Lock(); + } + ~CLock() + { + Unlock(); + + } + + void Unlock() + { + LeaveCriticalSection(m_pcs); + TRACE(_T("LC %d %s\n") , GetCurrentThreadId() , m_strFunc); + } + + void Lock() + { + TRACE(_T("EC %d %s\n") , GetCurrentThreadId(), m_strFunc); + EnterCriticalSection(m_pcs); + } + + +protected: + CRITICAL_SECTION* m_pcs; + CString m_strFunc; + +}; + +enum IOType +{ + IOInitialize, + IORead, + IOWrite, + IOIdle +}; + + +class OVERLAPPEDPLUS +{ +public: + OVERLAPPED m_ol; + IOType m_ioType; + + OVERLAPPEDPLUS(IOType ioType) { + ZeroMemory(this, sizeof(OVERLAPPEDPLUS)); + m_ioType = ioType; + } +}; +//lang2.1_3 + +struct ClientContext //򵥷ClientContextṹȻص SendSelectCommand +{ + SOCKET m_Socket; //׽ + // Store buffers + CBuffer m_WriteBuffer; + CBuffer m_CompressionBuffer; // յѹ + CBuffer m_DeCompressionBuffer; // ѹ + CBuffer m_ResendWriteBuffer; // ϴη͵ݰʧʱطʱ + + int m_Dialog[2]; // ŶԻбãһintͣڶCDialogĵַ + int m_nTransferProgress; + // Input Elements for Winsock + WSABUF m_wsaInBuffer; + BYTE m_byInBuffer[8192]; + + // Output elements for Winsock + WSABUF m_wsaOutBuffer; + HANDLE m_hWriteComplete; + + // Message counts... purely for example purposes + LONG m_nMsgIn; + LONG m_nMsgOut; + + BOOL m_bIsMainSocket; // Dzsocket + + ClientContext* m_pWriteContext; + ClientContext* m_pReadContext; +}; + +template<> +inline UINT AFXAPI HashKey(CString & strGuid) +{ + return HashKey( (LPCTSTR) strGuid); +} + +#include "Mapper.h" + +typedef void (CALLBACK* NOTIFYPROC)(LPVOID, ClientContext*, UINT nCode); + +typedef CList ContextList; + + +class CMainFrame; + +class CIOCPServer +{ +public: + void DisconnectAll(); + CIOCPServer(); + virtual ~CIOCPServer(); + + NOTIFYPROC m_pNotifyProc; + CMainFrame* m_pFrame; + + bool Initialize(NOTIFYPROC pNotifyProc, CMainFrame* pFrame, int nMaxConnections, int nPort); + + static unsigned __stdcall ListenThreadProc(LPVOID lpVoid); + static unsigned __stdcall ThreadPoolFunc(LPVOID WorkContext); + static CRITICAL_SECTION m_cs; + + void Send(ClientContext* pContext, LPBYTE lpData, UINT nSize); + void PostRecv(ClientContext* pContext); + + bool IsRunning(); + void Shutdown(); + void ResetConnection(ClientContext* pContext); + + LONG m_nCurrentThreads; + LONG m_nBusyThreads; + + + UINT m_nSendKbps; // ͼʱٶ + UINT m_nRecvKbps; // ܼʱٶ + UINT m_nMaxConnections; // +protected: + void InitializeClientRead(ClientContext* pContext); + BOOL AssociateSocketWithCompletionPort(SOCKET device, HANDLE hCompletionPort, DWORD dwCompletionKey); + void RemoveStaleClient(ClientContext* pContext, BOOL bGraceful); + void MoveToFreePool(ClientContext *pContext); + ClientContext* AllocateContext(); + + LONG m_nWorkerCnt; + + bool m_bInit; + bool m_bDisconnectAll; + BYTE m_bPacketFlag[5]; + void CloseCompletionPort(); + void OnAccept(); + bool InitializeIOCP(void); + void Stop(); + + ContextList m_listContexts; + ContextList m_listFreePool; + WSAEVENT m_hEvent; + SOCKET m_socListen; + HANDLE m_hKillEvent; + HANDLE m_hThread; + HANDLE m_hCompletionPort; + bool m_bTimeToKill; + CCpuUsage m_cpu; + + LONG m_nKeepLiveTime; // ʱ + + // Thread Pool Tunables + LONG m_nThreadPoolMin; + LONG m_nThreadPoolMax; + LONG m_nCPULoThreshold; + LONG m_nCPUHiThreshold; + + + CString GetHostName(SOCKET socket); + + void CreateStream(ClientContext* pContext); + + BEGIN_IO_MSG_MAP() + IO_MESSAGE_HANDLER(IORead, OnClientReading) + IO_MESSAGE_HANDLER(IOWrite, OnClientWriting) + IO_MESSAGE_HANDLER(IOInitialize, OnClientInitializing) + END_IO_MSG_MAP() + + bool OnClientInitializing (ClientContext* pContext, DWORD dwSize = 0); + bool OnClientReading (ClientContext* pContext, DWORD dwSize = 0); + bool OnClientWriting (ClientContext* pContext, DWORD dwSize = 0); + +}; + +#endif // !defined(AFX_IOCPSERVER_H__75B80E90_FD25_4FFB_B273_0090AA43BBDF__INCLUDED_) diff --git a/CcRemote/CcRemote/include/Mapper.h b/CcRemote/CcRemote/include/Mapper.h new file mode 100644 index 0000000..2bbd208 --- /dev/null +++ b/CcRemote/CcRemote/include/Mapper.h @@ -0,0 +1,27 @@ + +#ifndef __IO_MAPPER__ +#define __IO_MAPPER__ + +#define net_msg + +class __declspec(novtable) CIOMessageMap +{ +public: + virtual bool ProcessIOMessage(IOType clientIO, ClientContext* pContext, DWORD dwSize) = 0; +}; + +#define BEGIN_IO_MSG_MAP() \ +public: \ + bool ProcessIOMessage(IOType clientIO, ClientContext* pContext, DWORD dwSize = 0) \ + { \ + bool bRet = false; + +#define IO_MESSAGE_HANDLER(msg, func) \ + if (msg == clientIO) \ + bRet = func(pContext, dwSize); + +#define END_IO_MSG_MAP() \ + return bRet; \ + } + +#endif \ No newline at end of file diff --git a/CcRemote/CcRemote/pch.h b/CcRemote/CcRemote/pch.h index 9660927..e687e33 100644 --- a/CcRemote/CcRemote/pch.h +++ b/CcRemote/CcRemote/pch.h @@ -4,6 +4,8 @@ // 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。 // 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。 + + #ifndef PCH_H #define PCH_H @@ -11,3 +13,4 @@ #include "framework.h" #endif //PCH_H + diff --git a/CcRemote/Debug/CcRemote.exe b/CcRemote/Debug/CcRemote.exe index ebd5fa6..d0ddbae 100644 Binary files a/CcRemote/Debug/CcRemote.exe and b/CcRemote/Debug/CcRemote.exe differ diff --git a/CcRemote/Release/CcRemote.exe b/CcRemote/Release/CcRemote.exe new file mode 100644 index 0000000..e938ef9 Binary files /dev/null and b/CcRemote/Release/CcRemote.exe differ diff --git a/CcRemote/Release/CcRemote.iobj b/CcRemote/Release/CcRemote.iobj new file mode 100644 index 0000000..0480607 Binary files /dev/null and b/CcRemote/Release/CcRemote.iobj differ diff --git a/CcRemote/Release/CcRemote.ipdb b/CcRemote/Release/CcRemote.ipdb new file mode 100644 index 0000000..8b18e28 Binary files /dev/null and b/CcRemote/Release/CcRemote.ipdb differ diff --git a/common/Audio.cpp b/common/Audio.cpp new file mode 100644 index 0000000..7786d65 --- /dev/null +++ b/common/Audio.cpp @@ -0,0 +1,199 @@ +// Audio.cpp: implementation of the CAudio class. +// +////////////////////////////////////////////////////////////////////// + +#include "Audio.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CAudio::CAudio() +{ + m_hEventWaveIn = CreateEvent(NULL, false, false, NULL); + m_hStartRecord = CreateEvent(NULL, false, false, NULL); + m_hThreadCallBack = NULL; + m_nWaveInIndex = 0; + m_nWaveOutIndex = 0; + m_nBufferLength = 1000; // m_GSMWavefmt.wfx.nSamplesPerSec / 8(bit) + + m_bIsWaveInUsed = false; + m_bIsWaveOutUsed = false; + + for (int i = 0; i < 2; i++) + { + m_lpInAudioData[i] = new BYTE[m_nBufferLength]; + m_lpInAudioHdr[i] = new WAVEHDR; + + m_lpOutAudioData[i] = new BYTE[m_nBufferLength]; + m_lpOutAudioHdr[i] = new WAVEHDR; + } + + memset(&m_GSMWavefmt, 0, sizeof(GSM610WAVEFORMAT)); + + m_GSMWavefmt.wfx.wFormatTag = WAVE_FORMAT_GSM610; // ACM will auto convert wave format + m_GSMWavefmt.wfx.nChannels = 1; + m_GSMWavefmt.wfx.nSamplesPerSec = 8000; + m_GSMWavefmt.wfx.nAvgBytesPerSec = 1625; + m_GSMWavefmt.wfx.nBlockAlign = 65; + m_GSMWavefmt.wfx.wBitsPerSample = 0; + m_GSMWavefmt.wfx.cbSize = 2; + m_GSMWavefmt.wSamplesPerBlock = 320; +} + +CAudio::~CAudio() +{ + if (m_bIsWaveInUsed) + { + waveInStop(m_hWaveIn); + waveInReset(m_hWaveIn); + for (int i = 0; i < 2; i++) + waveInUnprepareHeader(m_hWaveIn, m_lpInAudioHdr[i], sizeof(WAVEHDR)); + waveInClose(m_hWaveIn); + TerminateThread(m_hThreadCallBack, -1); + } + + if (m_bIsWaveOutUsed) + { + waveOutReset(m_hWaveOut); + for (int i = 0; i < 2; i++) + waveOutUnprepareHeader(m_hWaveOut, m_lpInAudioHdr[i], sizeof(WAVEHDR)); + waveOutClose(m_hWaveOut); + } + + + for (int i = 0; i < 2; i++) + { + delete [] m_lpInAudioData[i]; + delete m_lpInAudioHdr[i]; + + delete [] m_lpOutAudioData[i]; + delete m_lpOutAudioHdr[i]; + } + + CloseHandle(m_hEventWaveIn); + CloseHandle(m_hStartRecord); + CloseHandle(m_hThreadCallBack); +} + +LPBYTE CAudio::getRecordBuffer(LPDWORD lpdwBytes) +{ + // Not open WaveIn yet, so open it... + if (!m_bIsWaveInUsed && !InitializeWaveIn()) + return NULL; + + if (lpdwBytes == NULL) + return NULL; + + SetEvent(m_hStartRecord); + WaitForSingleObject(m_hEventWaveIn, INFINITE); + *lpdwBytes = m_nBufferLength; + return m_lpInAudioData[m_nWaveInIndex]; +} + +bool CAudio::playBuffer(LPBYTE lpWaveBuffer, DWORD dwBytes) +{ + if (!m_bIsWaveOutUsed && !InitializeWaveOut()) + return NULL; + + for (int i = 0; i < dwBytes; i += m_nBufferLength) + { + memcpy(m_lpOutAudioData[m_nWaveOutIndex], lpWaveBuffer, m_nBufferLength); + waveOutWrite(m_hWaveOut, m_lpOutAudioHdr[m_nWaveOutIndex], sizeof(WAVEHDR)); + m_nWaveOutIndex = 1 - m_nWaveOutIndex; + } + return true; +} + +bool CAudio::InitializeWaveIn() +{ + if (!waveInGetNumDevs()) + return false; + + MMRESULT mmResult; + DWORD dwThreadID = 0; + m_hThreadCallBack = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)waveInCallBack, (LPVOID)this, CREATE_SUSPENDED, &dwThreadID); + mmResult = waveInOpen(&m_hWaveIn, (WORD)WAVE_MAPPER, &(m_GSMWavefmt.wfx), (LONG)dwThreadID, (LONG)0, CALLBACK_THREAD); + + if (mmResult != MMSYSERR_NOERROR) + return false; + + for (int i = 0; i < 2; i++) + { + m_lpInAudioHdr[i]->lpData = (LPSTR)m_lpInAudioData[i]; + m_lpInAudioHdr[i]->dwBufferLength = m_nBufferLength; + m_lpInAudioHdr[i]->dwFlags = 0; + m_lpInAudioHdr[i]->dwLoops = 0; + waveInPrepareHeader(m_hWaveIn, m_lpInAudioHdr[i], sizeof(WAVEHDR)); + } + + waveInAddBuffer(m_hWaveIn, m_lpInAudioHdr[m_nWaveInIndex], sizeof(WAVEHDR)); + + ResumeThread(m_hThreadCallBack); + waveInStart(m_hWaveIn); + + m_bIsWaveInUsed = true; + + return true; + +} + +bool CAudio::InitializeWaveOut() +{ + + if (!waveOutGetNumDevs()) + return false; + + for (int i = 0; i < 2; i++) + memset(m_lpOutAudioData[i], 0, m_nBufferLength); + + MMRESULT mmResult; + mmResult = waveOutOpen(&m_hWaveOut, (WORD)WAVE_MAPPER, &(m_GSMWavefmt.wfx), (LONG)0, (LONG)0, CALLBACK_NULL); + if (mmResult != MMSYSERR_NOERROR) + return false; + + for (i = 0; i < 2; i++) + { + m_lpOutAudioHdr[i]->lpData = (LPSTR)m_lpOutAudioData[i]; + m_lpOutAudioHdr[i]->dwBufferLength = m_nBufferLength; + m_lpOutAudioHdr[i]->dwFlags = 0; + m_lpOutAudioHdr[i]->dwLoops = 0; + waveOutPrepareHeader(m_hWaveOut, m_lpOutAudioHdr[i], sizeof(WAVEHDR)); + } + + m_bIsWaveOutUsed = true; + return true; +} + +DWORD WINAPI CAudio::waveInCallBack( LPVOID lparam ) +{ + CAudio *pThis = (CAudio *)lparam; + + MSG Msg; + while (GetMessage(&Msg, NULL, 0, 0)) + { + if (Msg.message == MM_WIM_DATA) + { + // ֪ͨݵ + SetEvent(pThis->m_hEventWaveIn); + // ȴʼ´¼ + WaitForSingleObject(pThis->m_hStartRecord, INFINITE); + + pThis->m_nWaveInIndex = 1 - pThis->m_nWaveInIndex; + + MMRESULT mmResult = waveInAddBuffer(pThis->m_hWaveIn, pThis->m_lpInAudioHdr[pThis->m_nWaveInIndex], sizeof(WAVEHDR)); + if (mmResult != MMSYSERR_NOERROR) + return -1; + + } + + // Why never happend this + if (Msg.message == MM_WIM_CLOSE) + break; + + TranslateMessage(&Msg); + DispatchMessage(&Msg); + } + + return 0; +} \ No newline at end of file diff --git a/common/Audio.h b/common/Audio.h new file mode 100644 index 0000000..350fa40 --- /dev/null +++ b/common/Audio.h @@ -0,0 +1,53 @@ +// Audio.h: interface for the CAudio class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_AUDIO_H__4DD286A3_85E9_4492_A1A5_C3B2D860BD1A__INCLUDED_) +#define AFX_AUDIO_H__4DD286A3_85E9_4492_A1A5_C3B2D860BD1A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +#include +#include +#include +#pragma comment(lib, "Winmm.lib") + +class CAudio +{ +public: + CAudio(); + virtual ~CAudio(); + int m_nBufferLength; + + LPBYTE m_lpInAudioData[2]; // + LPBYTE m_lpOutAudioData[2]; + + HWAVEIN m_hWaveIn; + int m_nWaveInIndex; + int m_nWaveOutIndex; + + HANDLE m_hEventWaveIn; // MM_WIM_DATA + HANDLE m_hStartRecord; // getRecordBuffer غ󴥷 + + LPBYTE getRecordBuffer(LPDWORD lpdwBytes); + bool playBuffer(LPBYTE lpWaveBuffer, DWORD dwBytes); +private: + HANDLE m_hThreadCallBack; + + LPWAVEHDR m_lpInAudioHdr[2]; + LPWAVEHDR m_lpOutAudioHdr[2]; + + HWAVEOUT m_hWaveOut; + + bool m_bIsWaveInUsed; + bool m_bIsWaveOutUsed; + GSM610WAVEFORMAT m_GSMWavefmt; + + bool InitializeWaveIn(); + bool InitializeWaveOut(); + + static DWORD WINAPI waveInCallBack(LPVOID lparam); +}; + +#endif // !defined(AFX_AUDIO_H__4DD286A3_85E9_4492_A1A5_C3B2D860BD1A__INCLUDED_) diff --git a/common/CursorInfo.h b/common/CursorInfo.h new file mode 100644 index 0000000..4b3295f --- /dev/null +++ b/common/CursorInfo.h @@ -0,0 +1,85 @@ +// CursorInfo.h: interface for the CCursorInfo class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_CURSORINFO_H__CE8C6529_4ACB_4BC3_96A8_C5C255A81289__INCLUDED_) +#define AFX_CURSORINFO_H__CE8C6529_4ACB_4BC3_96A8_C5C255A81289__INCLUDED_ +#include +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define MAX_CURSOR_TYPE 16 + +class CCursorInfo +{ +private: + LPCTSTR m_CursorResArray[MAX_CURSOR_TYPE]; + HCURSOR m_CursorHandleArray[MAX_CURSOR_TYPE]; + +public: + CCursorInfo() + { + LPCTSTR CursorResArray[MAX_CURSOR_TYPE] = + { + IDC_APPSTARTING, + IDC_ARROW, + IDC_CROSS, + IDC_HAND, + IDC_HELP, + IDC_IBEAM, + IDC_ICON, + IDC_NO, + IDC_SIZE, + IDC_SIZEALL, + IDC_SIZENESW, + IDC_SIZENS, + IDC_SIZENWSE, + IDC_SIZEWE, + IDC_UPARROW, + IDC_WAIT + }; + + for (int i = 0; i < MAX_CURSOR_TYPE; i++) + { + m_CursorResArray[i] = CursorResArray[i]; + m_CursorHandleArray[i] = LoadCursor(NULL, CursorResArray[i]); + } + } + + virtual ~CCursorInfo() + { + for (int i = 0; i < MAX_CURSOR_TYPE; i++) + DestroyCursor(m_CursorHandleArray[i]); + } + + + int getCurrentCursorIndex() + { + CURSORINFO ci; + ci.cbSize = sizeof(CURSORINFO); + if (!GetCursorInfo(&ci) || ci.flags != CURSOR_SHOWING) + return -1; + + + for (int i = 0; i < MAX_CURSOR_TYPE; i++) + { + if (ci.hCursor == m_CursorHandleArray[i]) + break; + } + DestroyCursor(ci.hCursor); + + int nIndex = i == MAX_CURSOR_TYPE ? -1 : i; + return nIndex; + } + + HCURSOR getCursorHandle( int nIndex ) + { + if (nIndex >= 0 && nIndex < MAX_CURSOR_TYPE) + return m_CursorHandleArray[nIndex]; + else + return NULL; + } +}; + +#endif // !defined(AFX_CURSORINFO_H__CE8C6529_4ACB_4BC3_96A8_C5C255A81289__INCLUDED_) diff --git a/common/VideoCodec.h b/common/VideoCodec.h new file mode 100644 index 0000000..5e5d657 --- /dev/null +++ b/common/VideoCodec.h @@ -0,0 +1,157 @@ +#if !defined(AFX_VIDEOCODEC_H_INCLUDED) +#define AFX_VIDEOCODEC_H_INCLUDED + +/* +õıѹ,ʹM263 +0x64697663,1684633187,Cinepak Codec by Radius 76032 >> 1860 +0x32335649,842225225,Intel Indeo(R) Video R3.2 76032 >> 475 +0x56555949,1448433993,Intel IYUV codec 76032 >> 38016 ѹ̫ +0x4356534d,1129730893,Microsoft Video 1 76032 >> 3202 +0x3336324d,859189837,Microsoft H.263 Video Codec 76032 >> 663 ԷֱҪ +0x33564d57,861293911,Microsoft Windows Media Video 9 76032 >> 196 +0x3234504d,842289229,Microsoft MPEG-4 Video Codec V2 76032 >> 349 + +M263ֻ֧176*144 352*288 (352*288 24ʵֻ֧biPlanes = 1) + + +һοõϵĴ + + // оٱװĽ(CODEC) +int EnumCodecs(int *fccHandler, char *strName) +{ + static int i = 0; + int nRet = 1; + HIC hIC; + ICINFO icInfo; + + if (fccHandler == NULL) + return 0; + + if(!ICInfo(ICTYPE_VIDEO, i, &icInfo)) + { + i = 0; + return 0; + } + hIC = ICOpen(icInfo.fccType, icInfo.fccHandler, ICMODE_QUERY); + + if (hIC) + { + ICGetInfo(hIC, &icInfo, sizeof(icInfo)); + *fccHandler = icInfo.fccHandler; + //ڵõszDescriptionUNICODE˫ִֽҪתΪASCII + if (strName != NULL) + wcstombs(strName, icInfo.szDescription, 256); + } + else nRet = -1; + + ICClose(hIC); + i++; + return nRet; +} + +Usage: + int fccHandler; + char strName[MAX_PATH]; + while(EnumCodecs(&fccHandler, strName)) + { + printf("0x%x,%s\n", fccHandler, strName); + } +*/ +class CVideoCodec +{ + COMPVARS m_cv; + HIC m_hIC; + BITMAPINFO* m_lpbmiInput; + BITMAPINFO m_bmiOutput; +public: + + bool InitCompressor(BITMAPINFO* lpbmi, DWORD fccHandler) + { + if (lpbmi == NULL) + return false; + + m_lpbmiInput = lpbmi; + + ZeroMemory(&m_cv, sizeof(m_cv)); + m_cv.cbSize = sizeof(m_cv); + m_cv.dwFlags = ICMF_COMPVARS_VALID; + m_cv.hic = m_hIC; + m_cv.fccType = ICTYPE_VIDEO; + m_cv.fccHandler = fccHandler; + m_cv.lpbiOut = NULL; + m_cv.lKey = 10; + m_cv.lDataRate = 6; + m_cv.lQ = ICQUALITY_HIGH; + + m_hIC = ICOpen(ICTYPE_VIDEO, m_cv.fccHandler, ICMODE_COMPRESS | ICMODE_DECOMPRESS); + + if (m_hIC == NULL) + { + return false; + } + + ICCompressGetFormat(m_hIC, m_lpbmiInput, &m_bmiOutput); + // ֤ + ICSendMessage(m_hIC, 0x60c9, 0xf7329ace, 0xacdeaea2); + + m_cv.hic = m_hIC; + m_cv.dwFlags = ICMF_COMPVARS_VALID; + + if (!ICSeqCompressFrameStart(&m_cv, m_lpbmiInput)) + { + return false; + } + + ICDecompressBegin(m_hIC, &m_bmiOutput , m_lpbmiInput); + + return true; + } + + bool DecodeVideoData(BYTE *pin, int len, BYTE* pout, int *lenr,DWORD flag) + { + if(!pin || !pout ||!m_hIC) + return false; + if (ICDecompress(m_hIC, flag, &m_bmiOutput.bmiHeader, pin, &m_lpbmiInput->bmiHeader, pout) != ICERR_OK) + return false; + + if (lenr) *lenr = m_lpbmiInput->bmiHeader.biSizeImage; + + return true; + } + + bool EncodeVideoData(BYTE* pin, int len, BYTE* pout, int* lenr, bool* pKey) + { + BYTE *p; + long s = 1; + BOOL k = true; + if ( !pin || !pout || len != (int)m_lpbmiInput->bmiHeader.biSizeImage || !m_hIC) + return false; + p = (BYTE*)ICSeqCompressFrame(&m_cv, 0, pin, &k, &s); + + if (!p) return false; + if (lenr) *lenr = s; + if (pKey) *pKey = k; + + CopyMemory(pout, p, s); + + return true; + } + + CVideoCodec() + { + m_lpbmiInput = NULL; + } + + virtual ~CVideoCodec() + { + // No init yet or init error + if (m_hIC == NULL) + return; + ICDecompressEnd(m_hIC); + ICSeqCompressFrameEnd(&m_cv); + ICCompressorFree(&m_cv); + ICClose(m_hIC); + } + +}; +#endif // !defined(AFX_VIDEOCODEC_H_INCLUDED) \ No newline at end of file diff --git a/common/macros.h b/common/macros.h new file mode 100644 index 0000000..993385c --- /dev/null +++ b/common/macros.h @@ -0,0 +1,119 @@ + +#if !defined(AFX_MACROS_H_INCLUDED) +#define AFX_MACROS_H_INCLUDED + +// BYTEҲ256 +enum +{ + // ļ䷽ʽ + TRANSFER_MODE_NORMAL = 0x00, // һ,ػԶѾУȡ + TRANSFER_MODE_ADDITION, // ׷ + TRANSFER_MODE_ADDITION_ALL, // ȫ׷ + TRANSFER_MODE_OVERWRITE, // + TRANSFER_MODE_OVERWRITE_ALL, // ȫ + TRANSFER_MODE_JUMP, // + TRANSFER_MODE_JUMP_ALL, // ȫ + TRANSFER_MODE_CANCEL, // ȡ + + // ƶ˷ + COMMAND_ACTIVED = 0x00, // ˿Լʼ + COMMAND_LIST_DRIVE, // гĿ¼ + COMMAND_LIST_FILES, // гĿ¼еļ + COMMAND_DOWN_FILES, // ļ + COMMAND_FILE_SIZE, // ϴʱļС + COMMAND_FILE_DATA, // ϴʱļ + COMMAND_EXCEPTION, // ䷢쳣Ҫ´ + COMMAND_CONTINUE, // + COMMAND_STOP, // ֹ + COMMAND_DELETE_FILE, // ɾļ + COMMAND_DELETE_DIRECTORY, // ɾĿ¼ + COMMAND_SET_TRANSFER_MODE, // ô䷽ʽ + COMMAND_CREATE_FOLDER, // ļ + COMMAND_RENAME_FILE, // ļļ + COMMAND_OPEN_FILE_SHOW, // ʾļ + COMMAND_OPEN_FILE_HIDE, // شļ + + COMMAND_SCREEN_SPY, // Ļ鿴 + COMMAND_SCREEN_RESET, // ıĻ + COMMAND_ALGORITHM_RESET, // ı㷨 + COMMAND_SCREEN_CTRL_ALT_DEL, // Ctrl+Alt+Del + COMMAND_SCREEN_CONTROL, // Ļ + COMMAND_SCREEN_BLOCK_INPUT, // ˼ + COMMAND_SCREEN_BLANK, // ˺ + COMMAND_SCREEN_CAPTURE_LAYER, // ׽ + COMMAND_SCREEN_GET_CLIPBOARD, // ȡԶ̼ + COMMAND_SCREEN_SET_CLIPBOARD, // Զ̼ + + COMMAND_WEBCAM, // ͷ + COMMAND_WEBCAM_ENABLECOMPRESS, // ͷҪ󾭹H263ѹ + COMMAND_WEBCAM_DISABLECOMPRESS, // ͷҪԭʼģʽ + COMMAND_WEBCAM_RESIZE, // ͷֱʣINT͵Ŀ + COMMAND_NEXT, // һ(ƶѾ򿪶Ի) + + COMMAND_KEYBOARD, // ̼¼ + COMMAND_KEYBOARD_OFFLINE, // ߼̼¼ + COMMAND_KEYBOARD_CLEAR, // ̼¼ + + COMMAND_AUDIO, // + + COMMAND_SYSTEM, // ϵͳ̣.... + COMMAND_PSLIST, // б + COMMAND_WSLIST, // б + COMMAND_DIALUPASS, // + COMMAND_KILLPROCESS, // رս + COMMAND_SHELL, // cmdshell + COMMAND_SESSION, // Ựػע, жأ + COMMAND_REMOVE, // жغ + COMMAND_DOWN_EXEC, // - ִ + COMMAND_UPDATE_SERVER, // - ظ + COMMAND_CLEAN_EVENT, // - ϵͳ־ + COMMAND_OPEN_URL_HIDE, // - شҳ + COMMAND_OPEN_URL_SHOW, // - ʾҳ + COMMAND_RENAME_REMARK, // ע + COMMAND_REPLAY_HEARTBEAT, // ظ + + + // ˷ıʶ + TOKEN_AUTH = 100, // Ҫ֤ + TOKEN_HEARTBEAT, // + TOKEN_LOGIN, // ߰ + TOKEN_DRIVE_LIST, // б + TOKEN_FILE_LIST, // ļб + TOKEN_FILE_SIZE, // ļСļʱ + TOKEN_FILE_DATA, // ļ + TOKEN_TRANSFER_FINISH, // + TOKEN_DELETE_FINISH, // ɾ + TOKEN_GET_TRANSFER_MODE, // õļ䷽ʽ + TOKEN_GET_FILEDATA, // Զ̵õļ + TOKEN_CREATEFOLDER_FINISH, // ļ + TOKEN_DATA_CONTINUE, // + TOKEN_RENAME_FINISH, // + TOKEN_EXCEPTION, // 쳣 + + TOKEN_BITMAPINFO, // Ļ鿴BITMAPINFO + TOKEN_FIRSTSCREEN, // Ļ鿴ĵһͼ + TOKEN_NEXTSCREEN, // Ļ鿴һͼ + TOKEN_CLIPBOARD_TEXT, // Ļ鿴ʱͼ + + + TOKEN_WEBCAM_BITMAPINFO, // ͷBITMAPINFOHEADER + TOKEN_WEBCAM_DIB, // ͷͼ + + TOKEN_AUDIO_START, // ʼ + TOKEN_AUDIO_DATA, // + + TOKEN_KEYBOARD_START, // ̼¼ʼ + TOKEN_KEYBOARD_DATA, // ̼¼ + + TOKEN_PSLIST, // б + TOKEN_WSLIST, // б + TOKEN_DIALUPASS, // + TOKEN_SHELL_START // Զն˿ʼ +}; + + +#define MAX_WRITE_RETRY 15 // дļ +#define MAX_SEND_BUFFER 1024 * 8 // ݳ +#define MAX_RECV_BUFFER 1024 * 8 // ݳ + +#endif // !defined(AFX_MACROS_H_INCLUDED) \ No newline at end of file diff --git a/common/zlib/zconf.h b/common/zlib/zconf.h new file mode 100644 index 0000000..eb0ae2e --- /dev/null +++ b/common/zlib/zconf.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/common/zlib/zlib.h b/common/zlib/zlib.h new file mode 100644 index 0000000..52cb529 --- /dev/null +++ b/common/zlib/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.4, March 11th, 2002 + + Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.4" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/common/zlib/zlib.lib b/common/zlib/zlib.lib new file mode 100644 index 0000000..55e5b14 Binary files /dev/null and b/common/zlib/zlib.lib differ