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 @@
falsev141true
- Unicode
+ MultiByteStatic
@@ -53,7 +53,7 @@
falsev141true
- Unicode
+ MultiByteStatic
@@ -91,12 +91,14 @@
UseLevel3Disabled
- true
+ falseWIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)pch.hWindows
+ ..\..\common\zlib\zlib.lib;%(AdditionalDependencies)
+ LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)false
@@ -114,12 +116,14 @@
UseLevel3Disabled
- true
+ false_WINDOWS;_DEBUG;%(PreprocessorDefinitions)pch.hWindows
+ ..\..\common\zlib\zlib.lib;%(AdditionalDependencies)
+ LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)false
@@ -139,14 +143,18 @@
MaxSpeedtruetrue
- true
+ falseWIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)pch.h
+ MultiThreadedDebugWindowstruetrue
+ ..\..\common\zlib\zlib.lib;%(AdditionalDependencies)
+ LIBCMT.lib;%(IgnoreSpecificDefaultLibraries)
+ /SAFESEH:NO %(AdditionalOptions)false
@@ -166,14 +174,18 @@
MaxSpeedtruetrue
- true
+ false_WINDOWS;NDEBUG;%(PreprocessorDefinitions)pch.h
+ MultiThreadedDebugWindowstruetrue
+ ..\..\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
+ CreateCreate
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