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 bool sure = this->_build_selectinfo(m_si, m_msec_timeout,
00095 false, false, false, true);
00096
00097 if (sure)
00098 {
00099 m_pending_callback = true;
00100 m_si.msec_timeout = 0;
00101 }
00102
00103
00104
00105
00106 SocketEventsMap sockmap;
00107 this->select_set(sockmap, &m_si.read, FD_READ);
00108 this->select_set(sockmap, &m_si.write, FD_WRITE);
00109 this->select_set(sockmap, &m_si.except, FD_OOB);
00110
00111
00112
00113 for (SocketEventsMap::iterator i = sockmap.begin(); i!=sockmap.end(); ++i)
00114 {
00115 SOCKET socket = (*i).first;
00116 long events = (*i).second;
00117
00118 int result = ::WSAAsyncSelect(socket, m_hWnd, WM_SELECT,
00119 events | FD_CONNECT | FD_CLOSE | FD_ACCEPT);
00120 assert(result == 0);
00121 }
00122
00123
00124 ::KillTimer(m_hWnd, TIMER_ID);
00125 if (m_si.msec_timeout >= 0)
00126 {
00127 ::SetTimer(m_hWnd, TIMER_ID, m_si.msec_timeout, NULL);
00128 }
00129
00130 m_select_in_progress = true;
00131 }
00132
00133 void WvWinStreamClone::post_poll()
00134 {
00135 bool sure = this->_process_selectinfo(m_si, true);
00136
00137 if (sure || m_pending_callback)
00138 {
00139 m_pending_callback = false;
00140 callback();
00141 if (globalstream) globalstream->callback();
00142 }
00143 }
00144
00145 void WvWinStreamClone::select_callback(SOCKET socket, int events, int error)
00146 {
00147 if (events | FD_READ) FD_SET(socket, &m_si.read);
00148 if (events | FD_WRITE) FD_SET(socket, &m_si.write);
00149 if (events | FD_OOB) FD_SET(socket, &m_si.except);
00150 m_pending_callback = true;
00151
00152 if (m_select_in_progress)
00153 {
00154 ::PostMessage(m_hWnd, WM_DONESELECT, 0, 0);
00155 m_select_in_progress = false;
00156 }
00157 }
00158
00159 LRESULT CALLBACK WvWinStreamClone::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00160 {
00161 switch (uMsg)
00162 {
00163 case WM_DONESELECT:
00164 {
00165 WvWinStreamClone *_this = s_wndmap[hwnd];
00166 assert(_this);
00167 _this->post_poll();
00168 _this->pre_poll();
00169
00170 break;
00171 }
00172
00173 case WM_SELECT:
00174 {
00175 WvWinStreamClone *_this = s_wndmap[hwnd];
00176 assert(_this);
00177 SOCKET socket = wParam;
00178 int events = WSAGETSELECTEVENT(lParam);
00179 int error = WSAGETSELECTERROR(lParam);
00180 _this->select_callback( socket, events, error );
00181
00182 break;
00183 }
00184
00185 case WM_TIMER:
00186 {
00187 ::PostMessage(hwnd, WM_DONESELECT, 0, 0);
00188
00189 break;
00190 }
00191
00192 default:
00193 return DefWindowProc(hwnd, uMsg, wParam, lParam);
00194 }
00195 return 0;
00196 }
00197
00198
00199
00200 void WvWinStreamClone::setclone(IWvStream *newclone)
00201 {
00202 WvStreamClone::setclone(newclone);
00203
00204 if (newclone != NULL)
00205 my_type = WvString("WvWinStreamClone:%s", newclone->wstype());
00206 else
00207 my_type = "WvWinStreamClone:(none)";
00208 }