ReactOS 0.4.16-dev-336-gb667d82
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
38static 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
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}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
HINSTANCE hInstance
Definition: charmap.c:19
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define E_NOTIMPL
Definition: ddrawi.h:99
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define TRACE_ON(x)
Definition: compat.h:75
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
INT WSAAPI WSAAsyncSelect(IN SOCKET s, IN HWND hWnd, IN UINT wMsg, IN LONG lEvent)
Definition: select.c:134
INT WSAAPI send(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags)
Definition: send.c:23
INT WINAPI WSAStartup(IN WORD wVersionRequested, OUT LPWSADATA lpWSAData)
Definition: startup.c:113
#define IPPROTO_TCP
Definition: ip.h:196
#define SOCK_STREAM
Definition: tcpip.h:118
unsigned int BOOL
Definition: ntddk_ex.h:94
Status
Definition: gdiplustypes.h:25
@ IXP_CONNECTING
Definition: imnxport.idl:246
@ IXP_CONNECTED
Definition: imnxport.idl:248
@ IXP_DISCONNECTED
Definition: imnxport.idl:253
@ IXP_FINDINGHOST
Definition: imnxport.idl:245
enum tagIXPSTATUS IXPSTATUS
void(* INETXPORT_COMPLETION_FUNCTION)(IInternetTransport *, char *, int)
HRESULT InternetTransport_Connect(InternetTransport *This, LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
static LRESULT CALLBACK InternetTransport_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
HRESULT InternetTransport_Write(InternetTransport *This, const char *pvData, int cbSize, INETXPORT_COMPLETION_FUNCTION fnCompletion)
HRESULT InternetTransport_Init(InternetTransport *This)
HRESULT InternetTransport_ChangeStatus(InternetTransport *This, IXPSTATUS Status)
#define IX_READ
#define IX_READLINE
HRESULT InternetTransport_DoCommand(InternetTransport *This, LPCSTR pszCommand, INETXPORT_COMPLETION_FUNCTION fnCompletion)
void InternetTransport_UnregisterClass(HINSTANCE hInstance)
HRESULT InternetTransport_GetServerInfo(InternetTransport *This, LPINETSERVER pInetServer)
HRESULT InternetTransport_InetServerFromAccount(InternetTransport *This, IImnAccount *pAccount, LPINETSERVER pInetServer)
HRESULT InternetTransport_ReadLine(InternetTransport *This, INETXPORT_COMPLETION_FUNCTION fnCompletion)
BOOL InternetTransport_RegisterClass(HINSTANCE hInstance)
static const WCHAR wszClassName[]
HRESULT InternetTransport_DropConnection(InternetTransport *This)
HRESULT InternetTransport_HandsOffCallback(InternetTransport *This)
HRESULT InternetTransport_GetStatus(InternetTransport *This, IXPSTATUS *pCurrentStatus)
#define S_OK
Definition: intsafe.h:52
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define closesocket
Definition: ncftp.h:477
unsigned int UINT
Definition: ndis.h:50
PVOID pBuffer
#define memset(x, y, z)
Definition: compat.h:39
namespace GUID const ADDRINFOEXW * hints
Definition: sock.c:80
INT WSAAPI shutdown(IN SOCKET s, IN INT how)
Definition: sockctrl.c:506
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwPort
Definition: imnxport.idl:226
CHAR szServerName[CCHMAX_SERVER_NAME]
Definition: imnxport.idl:223
LPCWSTR lpszClassName
Definition: winuser.h:3188
HINSTANCE hInstance
Definition: winuser.h:3183
WNDPROC lpfnWndProc
Definition: winuser.h:3180
size_t ai_addrlen
Definition: ws2def.h:669
struct sockaddr * ai_addr
Definition: ws2def.h:671
int ai_socktype
Definition: ws2def.h:667
int ai_protocol
Definition: ws2def.h:668
struct addrinfo * ai_next
Definition: ws2def.h:672
int ai_family
Definition: ws2def.h:666
Definition: winsock.h:66
#define GWLP_USERDATA
Definition: treelist.c:63
#define MAKEWORD(a, b)
Definition: typedefs.h:248
int ret
char * host
Definition: whois.c:55
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
_In_ ULONG _In_opt_ PVOID pvData
Definition: winddi.h:3749
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define S_FALSE
Definition: winerror.h:2357
#define WSAEWOULDBLOCK
Definition: winerror.h:1948
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define SD_BOTH
Definition: winsock.h:56
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:112
#define FD_READ
Definition: winsock.h:405
#define FD_ZERO(set)
Definition: winsock.h:96
int PASCAL FAR WSACleanup(void)
Definition: startup.c:60
#define PF_UNSPEC
Definition: winsock.h:371
#define SOCKET_ERROR
Definition: winsock.h:333
#define FD_SET(fd, set)
Definition: winsock.h:89
#define snprintf
Definition: wintirpc.h:48
#define GetWindowLongPtrW
Definition: winuser.h:4832
LRESULT WINAPI DefWindowProcW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
ATOM WINAPI RegisterClassW(_In_ CONST WNDCLASSW *)
#define CreateWindowW(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4319
BOOL WINAPI UnregisterClassW(_In_ LPCWSTR, HINSTANCE)
#define SetWindowLongPtrW
Definition: winuser.h:5358
BOOL WINAPI DestroyWindow(_In_ HWND)
#define NI_NUMERICHOST
Definition: ws2def.h:354
#define NI_NUMERICSERV
Definition: ws2def.h:356
#define getaddrinfo
Definition: wspiapi.h:44
#define getnameinfo
Definition: wspiapi.h:45
#define freeaddrinfo
Definition: wspiapi.h:46
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180