~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/inetcomm/internettransport.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Internet Messaging Transport Base Class
  3  *
  4  * Copyright 2006 Robert Shearman for CodeWeavers
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #define COBJMACROS
 22 
 23 #include "ws2tcpip.h"
 24 #include "windef.h"
 25 #include "winnt.h"
 26 #include "objbase.h"
 27 #include "ole2.h"
 28 #include "mimeole.h"
 29 
 30 #include <stdio.h>
 31 
 32 #include "wine/debug.h"
 33 
 34 #include "inetcomm_private.h"
 35 
 36 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
 37 
 38 static const WCHAR wszClassName[] = {'T','h','o','r','C','o','n','n','W','n','d','C','l','a','s','s',0};
 39 
 40 #define IX_READ     (WM_USER + 0)
 41 #define IX_READLINE (WM_USER + 1)
 42 #define IX_WRITE    (WM_USER + 2)
 43 
 44 HRESULT InternetTransport_Init(InternetTransport *This)
 45 {
 46     This->pCallback = NULL;
 47     This->Status = IXP_DISCONNECTED;
 48     This->Socket = -1;
 49     This->fCommandLogging = FALSE;
 50     This->fnCompletion = NULL;
 51 
 52     return S_OK;
 53 }
 54 
 55 HRESULT InternetTransport_GetServerInfo(InternetTransport *This, LPINETSERVER pInetServer)
 56 {
 57     if (This->Status == IXP_DISCONNECTED)
 58         return IXP_E_NOT_CONNECTED;
 59 
 60     *pInetServer = This->ServerInfo;
 61     return S_OK;
 62 }
 63 
 64 HRESULT InternetTransport_InetServerFromAccount(InternetTransport *This,
 65     IImnAccount *pAccount, LPINETSERVER pInetServer)
 66 {
 67     FIXME("(%p, %p): stub\n", pAccount, pInetServer);
 68     return E_NOTIMPL;
 69 }
 70 
 71 HRESULT InternetTransport_Connect(InternetTransport *This,
 72     LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
 73 {
 74     struct addrinfo *ai;
 75     struct addrinfo *ai_cur;
 76     struct addrinfo hints;
 77     int ret;
 78     char szPort[10];
 79 
 80     if (This->Status != IXP_DISCONNECTED)
 81         return IXP_E_ALREADY_CONNECTED;
 82 
 83     This->ServerInfo = *pInetServer;
 84     This->fCommandLogging = fCommandLogging;
 85 
 86     This->hwnd = CreateWindowW(wszClassName, wszClassName, 0, 0, 0, 0, 0, NULL, NULL, NULL, 0);
 87     if (!This->hwnd)
 88         return HRESULT_FROM_WIN32(GetLastError());
 89     SetWindowLongPtrW(This->hwnd, GWLP_USERDATA, (LONG_PTR)This);
 90 
 91     hints.ai_flags          = 0;
 92     hints.ai_family         = PF_UNSPEC;
 93     hints.ai_socktype       = SOCK_STREAM;
 94     hints.ai_protocol       = IPPROTO_TCP;
 95     hints.ai_addrlen        = 0;
 96     hints.ai_addr           = NULL;
 97     hints.ai_canonname      = NULL;
 98     hints.ai_next           = NULL;
 99 
100     snprintf(szPort, sizeof(szPort), "%d", (unsigned short)pInetServer->dwPort);
101 
102     InternetTransport_ChangeStatus(This, IXP_FINDINGHOST);
103 
104     ret = getaddrinfo(pInetServer->szServerName, szPort, &hints, &ai);
105     if (ret)
106     {
107         ERR("getaddrinfo failed: %d\n", ret);
108         return IXP_E_CANT_FIND_HOST;
109     }
110 
111     for (ai_cur = ai; ai_cur; ai_cur = ai->ai_next)
112     {
113         int so;
114 
115         if (TRACE_ON(inetcomm))
116         {
117             char host[256];
118             char service[256];
119             getnameinfo(ai_cur->ai_addr, ai_cur->ai_addrlen,
120                 host, sizeof(host), service, sizeof(service),
121                 NI_NUMERICHOST | NI_NUMERICSERV);
122             TRACE("trying %s:%s\n", host, service);
123         }
124 
125         InternetTransport_ChangeStatus(This, IXP_CONNECTING);
126 
127         so = socket(ai_cur->ai_family, ai_cur->ai_socktype, ai_cur->ai_protocol);
128         if (so == -1)
129         {
130             WARN("socket() failed\n");
131             continue;
132         }
133         This->Socket = so;
134 
135         /* FIXME: set to async */
136 
137         if (0 > connect(This->Socket, ai_cur->ai_addr, ai_cur->ai_addrlen))
138         {
139             WARN("connect() failed\n");
140             closesocket(This->Socket);
141             continue;
142         }
143         InternetTransport_ChangeStatus(This, IXP_CONNECTED);
144 
145         /* FIXME: call WSAAsyncSelect */
146 
147         freeaddrinfo(ai);
148         TRACE("connected\n");
149         return S_OK;
150     }
151 
152     freeaddrinfo(ai);
153 
154     return IXP_E_CANT_FIND_HOST;
155 }
156 
157 HRESULT InternetTransport_HandsOffCallback(InternetTransport *This)
158 {
159     if (!This->pCallback)
160         return S_FALSE;
161 
162     ITransportCallback_Release(This->pCallback);
163     This->pCallback = NULL;
164 
165     return S_OK;
166 }
167 
168 HRESULT InternetTransport_DropConnection(InternetTransport *This)
169 {
170     int ret;
171 
172     if (This->Status == IXP_DISCONNECTED)
173         return IXP_E_NOT_CONNECTED;
174 
175     ret = shutdown(This->Socket, SD_BOTH);
176 
177     ret = closesocket(This->Socket);
178 
179     DestroyWindow(This->hwnd);
180     This->hwnd = NULL;
181 
182     InternetTransport_ChangeStatus(This, IXP_DISCONNECTED);
183 
184     return S_OK;
185 }
186 
187 HRESULT InternetTransport_GetStatus(InternetTransport *This,
188     IXPSTATUS *pCurrentStatus)
189 {
190     *pCurrentStatus = This->Status;
191     return S_OK;
192 }
193 
194 HRESULT InternetTransport_ChangeStatus(InternetTransport *This, IXPSTATUS Status)
195 {
196     This->Status = Status;
197     if (This->pCallback)
198         ITransportCallback_OnStatus(This->pCallback, Status,
199             (IInternetTransport *)&This->u.vtbl);
200     return S_OK;
201 }
202 
203 HRESULT InternetTransport_ReadLine(InternetTransport *This,
204     INETXPORT_COMPLETION_FUNCTION fnCompletion)
205 {
206     if (This->Status == IXP_DISCONNECTED)
207         return IXP_E_NOT_CONNECTED;
208 
209     if (This->fnCompletion)
210         return IXP_E_BUSY;
211 
212     This->fnCompletion = fnCompletion;
213 
214     This->cbBuffer = 1024;
215     This->pBuffer = HeapAlloc(GetProcessHeap(), 0, This->cbBuffer);
216     This->iCurrentBufferOffset = 0;
217 
218     if (WSAAsyncSelect(This->Socket, This->hwnd, IX_READLINE, FD_READ) == SOCKET_ERROR)
219     {
220         ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError());
221         /* FIXME: handle error */
222     }
223     return S_OK;
224 }
225 
226 HRESULT InternetTransport_Write(InternetTransport *This, const char *pvData,
227     int cbSize, INETXPORT_COMPLETION_FUNCTION fnCompletion)
228 {
229     int ret;
230 
231     if (This->Status == IXP_DISCONNECTED)
232         return IXP_E_NOT_CONNECTED;
233 
234     if (This->fnCompletion)
235         return IXP_E_BUSY;
236 
237     /* FIXME: do this asynchronously */
238     ret = send(This->Socket, pvData, cbSize, 0);
239     if (ret == SOCKET_ERROR)
240     {
241         ERR("send failed with error %d\n", WSAGetLastError());
242         /* FIXME: handle error */
243     }
244 
245     fnCompletion((IInternetTransport *)&This->u.vtbl, NULL, 0);
246 
247     return S_OK;
248 }
249 
250 HRESULT InternetTransport_DoCommand(InternetTransport *This,
251     LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion)
252 {
253     if (This->Status == IXP_DISCONNECTED)
254         return IXP_E_NOT_CONNECTED;
255 
256     if (This->fnCompletion)
257         return IXP_E_BUSY;
258 
259     if (This->pCallback && This->fCommandLogging)
260     {
261         ITransportCallback_OnCommand(This->pCallback, CMD_SEND, (LPSTR)pszCommand, 0,
262             (IInternetTransport *)&This->u.vtbl);
263     }
264     return InternetTransport_Write(This, pszCommand, strlen(pszCommand), fnCompletion);
265 }
266 
267 static LRESULT CALLBACK InternetTransport_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
268 {
269     if (uMsg == IX_READ)
270     {
271         InternetTransport *This = (InternetTransport *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
272 
273         /* no work to do */
274         if (!This->fnCompletion)
275             return 0;
276 
277         while (This->iCurrentBufferOffset < This->cbBuffer)
278         {
279             if (recv(This->Socket, &This->pBuffer[This->iCurrentBufferOffset], 1, 0) <= 0)
280             {
281                 if (WSAGetLastError() == WSAEWOULDBLOCK)
282                     break;
283 
284                 ERR("recv failed with error %d\n", WSAGetLastError());
285                 /* FIXME: handle error */
286             }
287 
288             This->iCurrentBufferOffset++;
289         }
290         if (This->iCurrentBufferOffset == This->cbBuffer)
291         {
292             INETXPORT_COMPLETION_FUNCTION fnCompletion = This->fnCompletion;
293             char *pBuffer;
294 
295             This->fnCompletion = NULL;
296             pBuffer = This->pBuffer;
297             This->pBuffer = NULL;
298             fnCompletion((IInternetTransport *)&This->u.vtbl, pBuffer,
299                 This->iCurrentBufferOffset);
300             HeapFree(GetProcessHeap(), 0, pBuffer);
301             return 0;
302         }
303 
304         if (WSAAsyncSelect(This->Socket, hwnd, uMsg, FD_READ) == SOCKET_ERROR)
305         {
306             ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError());
307             /* FIXME: handle error */
308         }
309         return 0;
310     }
311     else if (uMsg == IX_READLINE)
312     {
313         InternetTransport *This = (InternetTransport *)GetWindowLongPtrW(hwnd, GWLP_USERDATA);
314 
315         /* no work to do */
316         if (!This->fnCompletion)
317             return 0;
318 
319         while (This->iCurrentBufferOffset < This->cbBuffer - 1)
320         {
321             fd_set infd;
322 
323             if (recv(This->Socket, &This->pBuffer[This->iCurrentBufferOffset], 1, 0) <= 0)
324             {
325                 if (WSAGetLastError() == WSAEWOULDBLOCK)
326                     break;
327 
328                 ERR("recv failed with error %d\n", WSAGetLastError());
329                 /* FIXME: handle error */
330                 return 0;
331             }
332 
333             if (This->pBuffer[This->iCurrentBufferOffset] == '\n')
334             {
335                 INETXPORT_COMPLETION_FUNCTION fnCompletion = This->fnCompletion;
336                 char *pBuffer;
337 
338                 This->fnCompletion = NULL;
339                 This->pBuffer[This->iCurrentBufferOffset++] = '\0';
340                 pBuffer = This->pBuffer;
341                 This->pBuffer = NULL;
342 
343                 fnCompletion((IInternetTransport *)&This->u.vtbl, pBuffer,
344                     This->iCurrentBufferOffset);
345 
346                 HeapFree(GetProcessHeap(), 0, pBuffer);
347                 return 0;
348             }
349             if (This->pBuffer[This->iCurrentBufferOffset] != '\r')
350                 This->iCurrentBufferOffset++;
351 
352             FD_ZERO(&infd);
353             FD_SET(This->Socket, &infd);
354         }
355         if (This->iCurrentBufferOffset == This->cbBuffer - 1)
356             return 0;
357 
358         if (WSAAsyncSelect(This->Socket, hwnd, uMsg, FD_READ) == SOCKET_ERROR)
359         {
360             ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError());
361             /* FIXME: handle error */
362         }
363         return 0;
364     }
365     else
366         return DefWindowProcW(hwnd, uMsg, wParam, lParam);
367 }
368 
369 BOOL InternetTransport_RegisterClass(HINSTANCE hInstance)
370 {
371     WNDCLASSW cls;
372     WSADATA wsadata;
373 
374     if (WSAStartup(MAKEWORD(2, 2), &wsadata))
375         return FALSE;
376 
377     memset(&cls, 0, sizeof(cls));
378     cls.hInstance     = hInstance;
379     cls.lpfnWndProc   = InternetTransport_WndProc;
380     cls.lpszClassName = wszClassName;
381 
382     return RegisterClassW(&cls);
383 }
384 
385 void InternetTransport_UnregisterClass(HINSTANCE hInstance)
386 {
387     UnregisterClassW(wszClassName, hInstance);
388     WSACleanup();
389 }
390 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.