ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

internettransport.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.