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

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

Version: ~ [ 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 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

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

~ [ 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.