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