00001
00002 #define WINVER 0x0500
00003 #include "wvwinstreamclone.h"
00004
00005 ATOM WvWinStreamClone::s_aClass = 0;
00006 WvWinStreamClone::WndVector WvWinStreamClone::s_wndpool;
00007 WvWinStreamClone::WndStreamMap WvWinStreamClone::s_wndmap;
00008
00009 HWND WvWinStreamClone::alloc_wnd()
00010 {
00011 if (s_wndpool.empty())
00012 {
00013 HWND hWnd = CreateWindow(
00014 "WvWinStreamClone",
00015 "WvWinStreamWindowName",
00016 WS_POPUP | WS_DISABLED,
00017 CW_USEDEFAULT,
00018 CW_USEDEFAULT,
00019 CW_USEDEFAULT,
00020 CW_USEDEFAULT,
00021 HWND_MESSAGE,
00022 NULL,
00023 NULL,
00024 NULL
00025 );
00026 assert(hWnd);
00027 s_wndpool.push_back(hWnd);
00028 }
00029
00030 HWND hWnd = s_wndpool.back();
00031 s_wndpool.pop_back();
00032
00033
00034 s_wndmap[hWnd] = this;
00035
00036 return hWnd;
00037 }
00038
00039 void WvWinStreamClone::free_wnd(HWND w)
00040 {
00041 s_wndpool.push_back(w);
00042 }
00043
00044 DWORD WvWinStreamClone::Initialize()
00045 {
00046 WNDCLASS wc;
00047 wc.style = CS_HREDRAW | CS_VREDRAW;
00048 wc.lpfnWndProc = WvWinStreamClone::WndProc;
00049 wc.cbClsExtra = 0;
00050 wc.cbWndExtra = 0;
00051 wc.hInstance = GetModuleHandle(NULL);
00052 wc.hIcon = NULL;
00053 wc.hCursor = NULL;
00054 wc.hbrBackground = NULL;
00055 wc.lpszMenuName = NULL;
00056 wc.lpszClassName = "WvWinStreamClone";
00057
00058 s_aClass = RegisterClass(&wc);
00059 if (!s_aClass)
00060 {
00061 DWORD error = GetLastError();
00062 return error;
00063 }
00064 return 0;
00065 }
00066
00067 WvWinStreamClone::WvWinStreamClone(WvStream * _cloned) :
00068 WvStreamClone(_cloned), m_pending_callback(false), m_select_in_progress(false),
00069 m_msec_timeout(500)
00070 {
00071 memset(&m_si, 0, sizeof(m_si));
00072 m_hWnd = alloc_wnd();
00073 pre_poll();
00074 }
00075
00076 WvWinStreamClone::~WvWinStreamClone()
00077 {
00078 free_wnd(m_hWnd);
00079 }
00080
00081
00082 void WvWinStreamClone::select_set(SocketEventsMap &sockmap, fd_set *set, long event )
00083 {
00084 for (unsigned i=0; i<set->fd_count; i++)
00085 {
00086 SOCKET &socket = set->fd_array[i];
00087 sockmap[socket] |= event;
00088 }
00089
00090 FD_ZERO(set);
00091 }
00092
00093 void WvWinStreamClone::pre_poll()
00094 {
00095 this->_build_selectinfo(m_si, m_msec_timeout,
00096 false, false, false, true);
00097
00098
00099
00100
00101 SocketEventsMap sockmap;
00102 this->select_set(sockmap, &m_si.read, FD_READ);
00103 this->select_set(sockmap, &m_si.write, FD_WRITE);
00104 this->select_set(sockmap, &m_si.except, FD_OOB);
00105
00106
00107
00108 for (SocketEventsMap::iterator i = sockmap.begin(); i!=sockmap.end(); ++i)
00109 {
00110 SOCKET socket = (*i).first;
00111 long events = (*i).second;
00112
00113 int result = ::WSAAsyncSelect(socket, m_hWnd, WM_SELECT,
00114 events | FD_CONNECT | FD_CLOSE | FD_ACCEPT);
00115 assert(result == 0);
00116 }
00117
00118
00119 ::KillTimer(m_hWnd, TIMER_ID);
00120 if (m_si.msec_timeout >= 0)
00121 {
00122 ::SetTimer(m_hWnd, TIMER_ID, m_si.msec_timeout, NULL);
00123 }
00124
00125 m_select_in_progress = true;
00126 }
00127
00128 void WvWinStreamClone::post_poll()
00129 {
00130 bool sure = this->_process_selectinfo(m_si, true);
00131
00132 if (sure || m_pending_callback)
00133 {
00134 m_pending_callback = false;
00135 callback();
00136 if (globalstream) globalstream->callback();
00137 }
00138 }
00139
00140 void WvWinStreamClone::select_callback(SOCKET socket, int events, int error)
00141 {
00142 if (events | FD_READ) FD_SET(socket, &m_si.read);
00143 if (events | FD_WRITE) FD_SET(socket, &m_si.write);
00144 if (events | FD_OOB) FD_SET(socket, &m_si.except);
00145 m_pending_callback = true;
00146
00147 if (m_select_in_progress)
00148 {
00149 ::PostMessage(m_hWnd, WM_DONESELECT, 0, 0);
00150 m_select_in_progress = false;
00151 }
00152 }
00153
00154 LRESULT CALLBACK WvWinStreamClone::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00155 {
00156 switch (uMsg)
00157 {
00158 case WM_DONESELECT:
00159 {
00160 WvWinStreamClone *_this = s_wndmap[hwnd];
00161 assert(_this);
00162 _this->post_poll();
00163 _this->pre_poll();
00164
00165 break;
00166 }
00167
00168 case WM_SELECT:
00169 {
00170 WvWinStreamClone *_this = s_wndmap[hwnd];
00171 assert(_this);
00172 SOCKET socket = wParam;
00173 int events = WSAGETSELECTEVENT(lParam);
00174 int error = WSAGETSELECTERROR(lParam);
00175 _this->select_callback( socket, events, error );
00176
00177 break;
00178 }
00179
00180 case WM_TIMER:
00181 {
00182 ::PostMessage(hwnd, WM_DONESELECT, 0, 0);
00183
00184 break;
00185 }
00186
00187 default:
00188 return DefWindowProc(hwnd, uMsg, wParam, lParam);
00189 }
00190 return 0;
00191 }
00192
00193
00194
00195 void WvWinStreamClone::setclone(IWvStream *newclone)
00196 {
00197 WvStreamClone::setclone(newclone);
00198
00199 if (newclone != NULL)
00200 my_type = WvString("WvWinStreamClone:%s", newclone->wstype());
00201 else
00202 my_type = "WvWinStreamClone:(none)";
00203 }