Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninternettransport.c
Go to the documentation of this file.
00001 /* 00002 * Internet Messaging Transport Base Class 00003 * 00004 * Copyright 2006 Robert Shearman for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 #define COBJMACROS 00022 00023 #include "ws2tcpip.h" 00024 #include "windef.h" 00025 #include "winnt.h" 00026 #include "objbase.h" 00027 #include "ole2.h" 00028 #include "mimeole.h" 00029 00030 #include <stdio.h> 00031 00032 #include "wine/debug.h" 00033 00034 #include "inetcomm_private.h" 00035 00036 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm); 00037 00038 static const WCHAR wszClassName[] = {'T','h','o','r','C','o','n','n','W','n','d','C','l','a','s','s',0}; 00039 00040 #define IX_READ (WM_USER + 0) 00041 #define IX_READLINE (WM_USER + 1) 00042 #define IX_WRITE (WM_USER + 2) 00043 00044 HRESULT InternetTransport_Init(InternetTransport *This) 00045 { 00046 This->pCallback = NULL; 00047 This->Status = IXP_DISCONNECTED; 00048 This->Socket = -1; 00049 This->fCommandLogging = FALSE; 00050 This->fnCompletion = NULL; 00051 00052 return S_OK; 00053 } 00054 00055 HRESULT InternetTransport_GetServerInfo(InternetTransport *This, LPINETSERVER pInetServer) 00056 { 00057 if (This->Status == IXP_DISCONNECTED) 00058 return IXP_E_NOT_CONNECTED; 00059 00060 *pInetServer = This->ServerInfo; 00061 return S_OK; 00062 } 00063 00064 HRESULT InternetTransport_InetServerFromAccount(InternetTransport *This, 00065 IImnAccount *pAccount, LPINETSERVER pInetServer) 00066 { 00067 FIXME("(%p, %p): stub\n", pAccount, pInetServer); 00068 return E_NOTIMPL; 00069 } 00070 00071 HRESULT InternetTransport_Connect(InternetTransport *This, 00072 LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging) 00073 { 00074 struct addrinfo *ai; 00075 struct addrinfo *ai_cur; 00076 struct addrinfo hints; 00077 int ret; 00078 char szPort[10]; 00079 00080 if (This->Status != IXP_DISCONNECTED) 00081 return IXP_E_ALREADY_CONNECTED; 00082 00083 This->ServerInfo = *pInetServer; 00084 This->fCommandLogging = fCommandLogging; 00085 00086 This->hwnd = CreateWindowW(wszClassName, wszClassName, 0, 0, 0, 0, 0, NULL, NULL, NULL, 0); 00087 if (!This->hwnd) 00088 return HRESULT_FROM_WIN32(GetLastError()); 00089 SetWindowLongPtrW(This->hwnd, GWLP_USERDATA, (LONG_PTR)This); 00090 00091 hints.ai_flags = 0; 00092 hints.ai_family = PF_UNSPEC; 00093 hints.ai_socktype = SOCK_STREAM; 00094 hints.ai_protocol = IPPROTO_TCP; 00095 hints.ai_addrlen = 0; 00096 hints.ai_addr = NULL; 00097 hints.ai_canonname = NULL; 00098 hints.ai_next = NULL; 00099 00100 snprintf(szPort, sizeof(szPort), "%d", (unsigned short)pInetServer->dwPort); 00101 00102 InternetTransport_ChangeStatus(This, IXP_FINDINGHOST); 00103 00104 ret = getaddrinfo(pInetServer->szServerName, szPort, &hints, &ai); 00105 if (ret) 00106 { 00107 ERR("getaddrinfo failed: %d\n", ret); 00108 return IXP_E_CANT_FIND_HOST; 00109 } 00110 00111 for (ai_cur = ai; ai_cur; ai_cur = ai->ai_next) 00112 { 00113 int so; 00114 00115 if (TRACE_ON(inetcomm)) 00116 { 00117 char host[256]; 00118 char service[256]; 00119 getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen, 00120 host, sizeof(host), service, sizeof(service), 00121 NI_NUMERICHOST | NI_NUMERICSERV); 00122 TRACE("trying %s:%s\n", host, service); 00123 } 00124 00125 InternetTransport_ChangeStatus(This, IXP_CONNECTING); 00126 00127 so = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol); 00128 if (so == -1) 00129 { 00130 WARN("socket() failed\n"); 00131 continue; 00132 } 00133 This->Socket = so; 00134 00135 /* FIXME: set to async */ 00136 00137 if (0 > connect(This->Socket, ai_cur->ai_addr, ai_cur->ai_addrlen)) 00138 { 00139 WARN("connect() failed\n"); 00140 closesocket(This->Socket); 00141 continue; 00142 } 00143 InternetTransport_ChangeStatus(This, IXP_CONNECTED); 00144 00145 /* FIXME: call WSAAsyncSelect */ 00146 00147 freeaddrinfo(ai); 00148 TRACE("connected\n"); 00149 return S_OK; 00150 } 00151 00152 freeaddrinfo(ai); 00153 00154 return IXP_E_CANT_FIND_HOST; 00155 } 00156 00157 HRESULT InternetTransport_HandsOffCallback(InternetTransport *This) 00158 { 00159 if (!This->pCallback) 00160 return S_FALSE; 00161 00162 ITransportCallback_Release(This->pCallback); 00163 This->pCallback = NULL; 00164 00165 return S_OK; 00166 } 00167 00168 HRESULT InternetTransport_DropConnection(InternetTransport *This) 00169 { 00170 if (This->Status == IXP_DISCONNECTED) 00171 return IXP_E_NOT_CONNECTED; 00172 00173 shutdown(This->Socket, SD_BOTH); 00174 00175 closesocket(This->Socket); 00176 00177 DestroyWindow(This->hwnd); 00178 This->hwnd = NULL; 00179 00180 InternetTransport_ChangeStatus(This, IXP_DISCONNECTED); 00181 00182 return S_OK; 00183 } 00184 00185 HRESULT InternetTransport_GetStatus(InternetTransport *This, 00186 IXPSTATUS *pCurrentStatus) 00187 { 00188 *pCurrentStatus = This->Status; 00189 return S_OK; 00190 } 00191 00192 HRESULT InternetTransport_ChangeStatus(InternetTransport *This, IXPSTATUS Status) 00193 { 00194 This->Status = Status; 00195 if (This->pCallback) 00196 ITransportCallback_OnStatus(This->pCallback, Status, 00197 (IInternetTransport *)&This->u.vtbl); 00198 return S_OK; 00199 } 00200 00201 HRESULT InternetTransport_ReadLine(InternetTransport *This, 00202 INETXPORT_COMPLETION_FUNCTION fnCompletion) 00203 { 00204 if (This->Status == IXP_DISCONNECTED) 00205 return IXP_E_NOT_CONNECTED; 00206 00207 if (This->fnCompletion) 00208 return IXP_E_BUSY; 00209 00210 This->fnCompletion = fnCompletion; 00211 00212 This->cbBuffer = 1024; 00213 This->pBuffer = HeapAlloc(GetProcessHeap(), 0, This->cbBuffer); 00214 This->iCurrentBufferOffset = 0; 00215 00216 if (WSAAsyncSelect(This->Socket, This->hwnd, IX_READLINE, FD_READ) == SOCKET_ERROR) 00217 { 00218 ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError()); 00219 /* FIXME: handle error */ 00220 } 00221 return S_OK; 00222 } 00223 00224 HRESULT InternetTransport_Write(InternetTransport *This, const char *pvData, 00225 int cbSize, INETXPORT_COMPLETION_FUNCTION fnCompletion) 00226 { 00227 int ret; 00228 00229 if (This->Status == IXP_DISCONNECTED) 00230 return IXP_E_NOT_CONNECTED; 00231 00232 if (This->fnCompletion) 00233 return IXP_E_BUSY; 00234 00235 /* FIXME: do this asynchronously */ 00236 ret = send(This->Socket, pvData, cbSize, 0); 00237 if (ret == SOCKET_ERROR) 00238 { 00239 ERR("send failed with error %d\n", WSAGetLastError()); 00240 /* FIXME: handle error */ 00241 } 00242 00243 fnCompletion((IInternetTransport *)&This->u.vtbl, NULL, 0); 00244 00245 return S_OK; 00246 } 00247 00248 HRESULT InternetTransport_DoCommand(InternetTransport *This, 00249 LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion) 00250 { 00251 if (This->Status == IXP_DISCONNECTED) 00252 return IXP_E_NOT_CONNECTED; 00253 00254 if (This->fnCompletion) 00255 return IXP_E_BUSY; 00256 00257 if (This->pCallback && This->fCommandLogging) 00258 { 00259 ITransportCallback_OnCommand(This->pCallback, CMD_SEND, (LPSTR)pszCommand, 0, 00260 (IInternetTransport *)&This->u.vtbl); 00261 } 00262 return InternetTransport_Write(This, pszCommand, strlen(pszCommand), fnCompletion); 00263 } 00264 00265 static LRESULT CALLBACK InternetTransport_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 00266 { 00267 if (uMsg == IX_READ) 00268 { 00269 InternetTransport *This = (InternetTransport *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); 00270 00271 /* no work to do */ 00272 if (!This->fnCompletion) 00273 return 0; 00274 00275 while (This->iCurrentBufferOffset < This->cbBuffer) 00276 { 00277 if (recv(This->Socket, &This->pBuffer[This->iCurrentBufferOffset], 1, 0) <= 0) 00278 { 00279 if (WSAGetLastError() == WSAEWOULDBLOCK) 00280 break; 00281 00282 ERR("recv failed with error %d\n", WSAGetLastError()); 00283 /* FIXME: handle error */ 00284 } 00285 00286 This->iCurrentBufferOffset++; 00287 } 00288 if (This->iCurrentBufferOffset == This->cbBuffer) 00289 { 00290 INETXPORT_COMPLETION_FUNCTION fnCompletion = This->fnCompletion; 00291 char *pBuffer; 00292 00293 This->fnCompletion = NULL; 00294 pBuffer = This->pBuffer; 00295 This->pBuffer = NULL; 00296 fnCompletion((IInternetTransport *)&This->u.vtbl, pBuffer, 00297 This->iCurrentBufferOffset); 00298 HeapFree(GetProcessHeap(), 0, pBuffer); 00299 return 0; 00300 } 00301 00302 if (WSAAsyncSelect(This->Socket, hwnd, uMsg, FD_READ) == SOCKET_ERROR) 00303 { 00304 ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError()); 00305 /* FIXME: handle error */ 00306 } 00307 return 0; 00308 } 00309 else if (uMsg == IX_READLINE) 00310 { 00311 InternetTransport *This = (InternetTransport *)GetWindowLongPtrW(hwnd, GWLP_USERDATA); 00312 00313 /* no work to do */ 00314 if (!This->fnCompletion) 00315 return 0; 00316 00317 while (This->iCurrentBufferOffset < This->cbBuffer - 1) 00318 { 00319 fd_set infd; 00320 00321 if (recv(This->Socket, &This->pBuffer[This->iCurrentBufferOffset], 1, 0) <= 0) 00322 { 00323 if (WSAGetLastError() == WSAEWOULDBLOCK) 00324 break; 00325 00326 ERR("recv failed with error %d\n", WSAGetLastError()); 00327 /* FIXME: handle error */ 00328 return 0; 00329 } 00330 00331 if (This->pBuffer[This->iCurrentBufferOffset] == '\n') 00332 { 00333 INETXPORT_COMPLETION_FUNCTION fnCompletion = This->fnCompletion; 00334 char *pBuffer; 00335 00336 This->fnCompletion = NULL; 00337 This->pBuffer[This->iCurrentBufferOffset++] = '\0'; 00338 pBuffer = This->pBuffer; 00339 This->pBuffer = NULL; 00340 00341 fnCompletion((IInternetTransport *)&This->u.vtbl, pBuffer, 00342 This->iCurrentBufferOffset); 00343 00344 HeapFree(GetProcessHeap(), 0, pBuffer); 00345 return 0; 00346 } 00347 if (This->pBuffer[This->iCurrentBufferOffset] != '\r') 00348 This->iCurrentBufferOffset++; 00349 00350 FD_ZERO(&infd); 00351 FD_SET(This->Socket, &infd); 00352 } 00353 if (This->iCurrentBufferOffset == This->cbBuffer - 1) 00354 return 0; 00355 00356 if (WSAAsyncSelect(This->Socket, hwnd, uMsg, FD_READ) == SOCKET_ERROR) 00357 { 00358 ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError()); 00359 /* FIXME: handle error */ 00360 } 00361 return 0; 00362 } 00363 else 00364 return DefWindowProcW(hwnd, uMsg, wParam, lParam); 00365 } 00366 00367 BOOL InternetTransport_RegisterClass(HINSTANCE hInstance) 00368 { 00369 WNDCLASSW cls; 00370 WSADATA wsadata; 00371 00372 if (WSAStartup(MAKEWORD(2, 2), &wsadata)) 00373 return FALSE; 00374 00375 memset(&cls, 0, sizeof(cls)); 00376 cls.hInstance = hInstance; 00377 cls.lpfnWndProc = InternetTransport_WndProc; 00378 cls.lpszClassName = wszClassName; 00379 00380 return RegisterClassW(&cls); 00381 } 00382 00383 void InternetTransport_UnregisterClass(HINSTANCE hInstance) 00384 { 00385 UnregisterClassW(wszClassName, hInstance); 00386 WSACleanup(); 00387 } Generated on Fri May 25 2012 04:22:07 for ReactOS by
1.7.6.1
|