ReactOS  0.4.13-dev-52-g0efcfec
internettransport.c
Go to the documentation of this file.
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 
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 
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 
56 {
57  if (This->Status == IXP_DISCONNECTED)
58  return IXP_E_NOT_CONNECTED;
59 
60  *pInetServer = This->ServerInfo;
61  return S_OK;
62 }
63 
65  IImnAccount *pAccount, LPINETSERVER pInetServer)
66 {
67  FIXME("(%p, %p): stub\n", pAccount, pInetServer);
68  return E_NOTIMPL;
69 }
70 
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)
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 
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),
122  TRACE("trying %s:%s\n", host, service);
123  }
124 
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  }
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 
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 
169 {
170  if (This->Status == IXP_DISCONNECTED)
171  return IXP_E_NOT_CONNECTED;
172 
173  shutdown(This->Socket, SD_BOTH);
174 
175  closesocket(This->Socket);
176 
177  DestroyWindow(This->hwnd);
178  This->hwnd = NULL;
179 
181 
182  return S_OK;
183 }
184 
186  IXPSTATUS *pCurrentStatus)
187 {
188  *pCurrentStatus = This->Status;
189  return S_OK;
190 }
191 
193 {
194  This->Status = Status;
195  if (This->pCallback)
196  ITransportCallback_OnStatus(This->pCallback, Status,
197  (IInternetTransport *)&This->u.vtbl);
198  return S_OK;
199 }
200 
202  INETXPORT_COMPLETION_FUNCTION fnCompletion)
203 {
204  if (This->Status == IXP_DISCONNECTED)
205  return IXP_E_NOT_CONNECTED;
206 
207  if (This->fnCompletion)
208  return IXP_E_BUSY;
209 
210  This->fnCompletion = fnCompletion;
211 
212  This->cbBuffer = 1024;
213  This->pBuffer = HeapAlloc(GetProcessHeap(), 0, This->cbBuffer);
214  This->iCurrentBufferOffset = 0;
215 
216  if (WSAAsyncSelect(This->Socket, This->hwnd, IX_READLINE, FD_READ) == SOCKET_ERROR)
217  {
218  ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError());
219  /* FIXME: handle error */
220  }
221  return S_OK;
222 }
223 
225  int cbSize, INETXPORT_COMPLETION_FUNCTION fnCompletion)
226 {
227  int ret;
228 
229  if (This->Status == IXP_DISCONNECTED)
230  return IXP_E_NOT_CONNECTED;
231 
232  if (This->fnCompletion)
233  return IXP_E_BUSY;
234 
235  /* FIXME: do this asynchronously */
236  ret = send(This->Socket, pvData, cbSize, 0);
237  if (ret == SOCKET_ERROR)
238  {
239  ERR("send failed with error %d\n", WSAGetLastError());
240  /* FIXME: handle error */
241  }
242 
243  fnCompletion((IInternetTransport *)&This->u.vtbl, NULL, 0);
244 
245  return S_OK;
246 }
247 
249  LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion)
250 {
251  if (This->Status == IXP_DISCONNECTED)
252  return IXP_E_NOT_CONNECTED;
253 
254  if (This->fnCompletion)
255  return IXP_E_BUSY;
256 
257  if (This->pCallback && This->fCommandLogging)
258  {
259  ITransportCallback_OnCommand(This->pCallback, CMD_SEND, (LPSTR)pszCommand, 0,
260  (IInternetTransport *)&This->u.vtbl);
261  }
262  return InternetTransport_Write(This, pszCommand, strlen(pszCommand), fnCompletion);
263 }
264 
266 {
267  if (uMsg == IX_READ)
268  {
270 
271  /* no work to do */
272  if (!This->fnCompletion)
273  return 0;
274 
275  while (This->iCurrentBufferOffset < This->cbBuffer)
276  {
277  if (recv(This->Socket, &This->pBuffer[This->iCurrentBufferOffset], 1, 0) <= 0)
278  {
280  break;
281 
282  ERR("recv failed with error %d\n", WSAGetLastError());
283  /* FIXME: handle error */
284  }
285 
286  This->iCurrentBufferOffset++;
287  }
288  if (This->iCurrentBufferOffset == This->cbBuffer)
289  {
290  INETXPORT_COMPLETION_FUNCTION fnCompletion = This->fnCompletion;
291  char *pBuffer;
292 
293  This->fnCompletion = NULL;
294  pBuffer = This->pBuffer;
295  This->pBuffer = NULL;
296  fnCompletion((IInternetTransport *)&This->u.vtbl, pBuffer,
297  This->iCurrentBufferOffset);
299  return 0;
300  }
301 
302  if (WSAAsyncSelect(This->Socket, hwnd, uMsg, FD_READ) == SOCKET_ERROR)
303  {
304  ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError());
305  /* FIXME: handle error */
306  }
307  return 0;
308  }
309  else if (uMsg == IX_READLINE)
310  {
312 
313  /* no work to do */
314  if (!This->fnCompletion)
315  return 0;
316 
317  while (This->iCurrentBufferOffset < This->cbBuffer - 1)
318  {
319  fd_set infd;
320 
321  if (recv(This->Socket, &This->pBuffer[This->iCurrentBufferOffset], 1, 0) <= 0)
322  {
324  break;
325 
326  ERR("recv failed with error %d\n", WSAGetLastError());
327  /* FIXME: handle error */
328  return 0;
329  }
330 
331  if (This->pBuffer[This->iCurrentBufferOffset] == '\n')
332  {
333  INETXPORT_COMPLETION_FUNCTION fnCompletion = This->fnCompletion;
334  char *pBuffer;
335 
336  This->fnCompletion = NULL;
337  This->pBuffer[This->iCurrentBufferOffset++] = '\0';
338  pBuffer = This->pBuffer;
339  This->pBuffer = NULL;
340 
341  fnCompletion((IInternetTransport *)&This->u.vtbl, pBuffer,
342  This->iCurrentBufferOffset);
343 
345  return 0;
346  }
347  if (This->pBuffer[This->iCurrentBufferOffset] != '\r')
348  This->iCurrentBufferOffset++;
349 
350  FD_ZERO(&infd);
351  FD_SET(This->Socket, &infd);
352  }
353  if (This->iCurrentBufferOffset == This->cbBuffer - 1)
354  return 0;
355 
356  if (WSAAsyncSelect(This->Socket, hwnd, uMsg, FD_READ) == SOCKET_ERROR)
357  {
358  ERR("WSAAsyncSelect failed with error %d\n", WSAGetLastError());
359  /* FIXME: handle error */
360  }
361  return 0;
362  }
363  else
364  return DefWindowProcW(hwnd, uMsg, wParam, lParam);
365 }
366 
368 {
369  WNDCLASSW cls;
370  WSADATA wsadata;
371 
372  if (WSAStartup(MAKEWORD(2, 2), &wsadata))
373  return FALSE;
374 
375  memset(&cls, 0, sizeof(cls));
376  cls.hInstance = hInstance;
379 
380  return RegisterClassW(&cls);
381 }
382 
384 {
386  WSACleanup();
387 }
Definition: winsock.h:66
HRESULT InternetTransport_DoCommand(InternetTransport *This, LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion)
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
#define SOCKET_ERROR
Definition: winsock.h:333
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
HRESULT InternetTransport_GetServerInfo(InternetTransport *This, LPINETSERVER pInetServer)
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
#define freeaddrinfo
Definition: wspiapi.h:46
#define NI_NUMERICHOST
Definition: ws2def.h:354
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define MAKEWORD(a, b)
Definition: typedefs.h:247
HRESULT InternetTransport_HandsOffCallback(InternetTransport *This)
#define WARN(fmt,...)
Definition: debug.h:111
char * host
Definition: whois.c:55
#define CALLBACK
Definition: compat.h:27
ISF_QUERYAUTHSUPPORT struct INETSERVER * LPINETSERVER
INT WSAAPI WSACleanup(VOID)
Definition: startup.c:60
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define snprintf
Definition: wintirpc.h:48
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define NI_NUMERICSERV
Definition: ws2def.h:356
#define FD_READ
Definition: winsock.h:405
UINT_PTR WPARAM
Definition: windef.h:207
#define GetWindowLongPtrW
Definition: winuser.h:4698
#define FD_ZERO(set)
Definition: winsock.h:96
char * LPSTR
Definition: xmlstorage.h:182
#define FD_SET(fd, set)
Definition: winsock.h:89
BOOL WINAPI DestroyWindow(_In_ HWND)
INT WSAAPI connect(IN SOCKET s, IN CONST struct sockaddr *name, IN INT namelen)
Definition: sockctrl.c:23
static LRESULT CALLBACK InternetTransport_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4185
HRESULT InternetTransport_Write(InternetTransport *This, const char *pvData, int cbSize, INETXPORT_COMPLETION_FUNCTION fnCompletion)
WPARAM wParam
Definition: combotst.c:138
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
HINSTANCE hInstance
Definition: charmap.c:20
#define closesocket
Definition: main.c:39
unsigned int BOOL
Definition: ntddk_ex.h:94
WNDPROC lpfnWndProc
Definition: winuser.h:3130
#define FIXME(fmt,...)
Definition: debug.h:110
#define S_FALSE
Definition: winerror.h:2357
#define GWLP_USERDATA
Definition: treelist.c:63
static const WCHAR wszClassName[]
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3748
smooth NULL
Definition: ftsmooth.c:416
PVOID pBuffer
INT WSAAPI WSAAsyncSelect(IN SOCKET s, IN HWND hWnd, IN UINT wMsg, IN LONG lEvent)
Definition: select.c:134
LPCWSTR lpszClassName
Definition: winuser.h:3138
LONG_PTR LPARAM
Definition: windef.h:208
const char * LPCSTR
Definition: xmlstorage.h:183
HRESULT InternetTransport_ChangeStatus(InternetTransport *This, IXPSTATUS Status)
HRESULT InternetTransport_InetServerFromAccount(InternetTransport *This, IImnAccount *pAccount, LPINETSERVER pInetServer)
#define TRACE(s)
Definition: solgame.cpp:4
INT WSAAPI WSAGetLastError(VOID)
Definition: dllmain.c:112
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
HRESULT InternetTransport_Init(InternetTransport *This)
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:77
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
#define IX_READ
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
#define PF_UNSPEC
Definition: winsock.h:371
HRESULT InternetTransport_GetStatus(InternetTransport *This, IXPSTATUS *pCurrentStatus)
void(* INETXPORT_COMPLETION_FUNCTION)(IInternetTransport *, char *, int)
int ret
#define IX_READLINE
WINE_DEFAULT_DEBUG_CHANNEL(inetcomm)
int ai_protocol
Definition: ws2def.h:668
BOOL InternetTransport_RegisterClass(HINSTANCE hInstance)
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
#define S_OK
Definition: intsafe.h:59
int ai_socktype
Definition: ws2def.h:667
#define E_NOTIMPL
Definition: ddrawi.h:99
#define getnameinfo
Definition: wspiapi.h:45
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define SD_BOTH
Definition: winsock.h:56
unsigned int UINT
Definition: ndis.h:50
void InternetTransport_UnregisterClass(HINSTANCE hInstance)
enum tagIXPSTATUS IXPSTATUS
HINSTANCE hInstance
Definition: winuser.h:3133
struct addrinfo * ai_next
Definition: ws2def.h:672
#define SetWindowLongPtrW
Definition: winuser.h:5215
size_t ai_addrlen
Definition: ws2def.h:669
#define SOCK_STREAM
Definition: tcpip.h:118
HRESULT InternetTransport_Connect(InternetTransport *This, LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
LONG_PTR LRESULT
Definition: windef.h:209
#define memset(x, y, z)
Definition: compat.h:39
#define TRACE_ON(x)
Definition: compat.h:65
LPARAM lParam
Definition: combotst.c:139
HRESULT InternetTransport_ReadLine(InternetTransport *This, INETXPORT_COMPLETION_FUNCTION fnCompletion)
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
#define HeapFree(x, y, z)
Definition: compat.h:394
struct sockaddr * ai_addr
Definition: ws2def.h:671
HRESULT InternetTransport_DropConnection(InternetTransport *This)
#define getaddrinfo
Definition: wspiapi.h:44
int ai_family
Definition: ws2def.h:666