Merge pull request #25959 from neo1973/TagLib_deprecation_warnings
[xbmc.git] / lib / libUPnP / Neptune / Source / System / WinRT / NptWinRtSockets.cpp
blob89ad5733a20d417e0d833b81cc274e68aec2f625
1 /*****************************************************************
3 | Neptune - Sockets :: WinRT Implementation
5 | (c) 2001-2012 Gilles Boccon-Gibod
6 | Author: Gilles Boccon-Gibod (bok@bok.net)
8 ****************************************************************/
10 /*----------------------------------------------------------------------
11 | includes
12 +---------------------------------------------------------------------*/
13 #include "NptWinRtPch.h"
15 using namespace Platform;
16 using namespace Windows::Foundation;
17 using namespace Windows::Foundation::Collections;
18 using namespace Windows::Networking;
19 using namespace Windows::Networking::Sockets;
20 using namespace Windows::Storage::Streams;
21 using namespace Concurrency;
23 /*----------------------------------------------------------------------
24 | logging
25 +---------------------------------------------------------------------*/
26 NPT_SET_LOCAL_LOGGER("neptune.sockets.winrt")
28 /*----------------------------------------------------------------------
29 | constants
30 +---------------------------------------------------------------------*/
31 const DWORD NPT_WINRT_SOCKET_DEFAULT_READ_TIMEOUT = 30000;
32 const DWORD NPT_WINRT_SOCKET_DEFAULT_WRITE_TIMEOUT = 30000;
34 /*----------------------------------------------------------------------
35 | NPT_WinRtTcpClientSocket
36 +---------------------------------------------------------------------*/
37 class NPT_WinRtTcpClientSocket : public NPT_SocketInterface
39 public:
40 // constructors and destructor
41 NPT_WinRtTcpClientSocket();
42 virtual ~NPT_WinRtTcpClientSocket();
44 // NPT_SocketInterface methods
45 NPT_Result Bind(const NPT_SocketAddress& address, bool reuse_address = true);
46 NPT_Result Connect(const NPT_SocketAddress& address, NPT_Timeout timeout);
47 NPT_Result GetInputStream(NPT_InputStreamReference& stream);
48 NPT_Result GetOutputStream(NPT_OutputStreamReference& stream);
49 NPT_Result GetInfo(NPT_SocketInfo& info);
50 NPT_Result SetReadTimeout(NPT_Timeout timeout);
51 NPT_Result SetWriteTimeout(NPT_Timeout timeout);
52 NPT_Result Cancel(bool shutdown);
54 protected:
55 StreamSocket^ m_Socket;
56 HostName^ m_RemoteHostName;
57 HANDLE m_WaitEvent;
58 NPT_Timeout m_ReadTimeout;
59 NPT_Timeout m_WriteTimeout;
62 /*----------------------------------------------------------------------
63 | NPT_WinRtSocketInputStream
64 +---------------------------------------------------------------------*/
65 class NPT_WinRtSocketInputStream : public NPT_InputStream
67 public:
68 // constructors and destructor
69 NPT_WinRtSocketInputStream(StreamSocket^ socket, NPT_Timeout timeout);
70 virtual ~NPT_WinRtSocketInputStream();
72 // NPT_InputStream methods
73 NPT_Result Read(void* buffer,
74 NPT_Size bytes_to_read,
75 NPT_Size* bytes_read);
76 NPT_Result Seek(NPT_Position offset);
77 NPT_Result Tell(NPT_Position& where);
78 NPT_Result GetSize(NPT_LargeSize& size);
79 NPT_Result GetAvailable(NPT_LargeSize& available);
81 private:
82 StreamSocket^ m_Socket;
83 IInputStream^ m_InputStream;
84 DataReader^ m_Reader;
85 HANDLE m_WaitEvent;
86 NPT_Timeout m_Timeout;
89 /*----------------------------------------------------------------------
90 | NPT_WinRtSocketOutputStream
91 +---------------------------------------------------------------------*/
92 class NPT_WinRtSocketOutputStream : public NPT_OutputStream
94 public:
95 // constructors and destructor
96 NPT_WinRtSocketOutputStream(StreamSocket^ socket, NPT_Timeout timeout);
97 virtual ~NPT_WinRtSocketOutputStream();
99 // NPT_OutputStream methods
100 NPT_Result Write(const void* buffer,
101 NPT_Size bytes_to_write,
102 NPT_Size* bytes_written);
103 NPT_Result Seek(NPT_Position offset);
104 NPT_Result Tell(NPT_Position& where);
105 NPT_Result Flush();
107 private:
108 StreamSocket^ m_Socket;
109 IOutputStream^ m_OutputStream;
110 DataWriter^ m_Writer;
111 HANDLE m_WaitEvent;
112 NPT_Timeout m_Timeout;
115 /*----------------------------------------------------------------------
116 | StringFromUTF8
117 +---------------------------------------------------------------------*/
118 static String^
119 StringFromUTF8(const char* utf)
121 unsigned int utf_len = NPT_StringLength(utf);
122 unsigned int wide_len = utf_len;
123 wchar_t* wide = new wchar_t[wide_len+1];
124 int result = MultiByteToWideChar(CP_UTF8,
126 utf,
127 utf_len+1,
128 wide,
129 wide_len+1);
130 String^ str;
131 if (result) {
132 str = ref new String(wide);
133 } else {
134 str = ref new String();
136 delete[] wide;
137 return str;
140 /*----------------------------------------------------------------------
141 | TranslateHResult
142 +---------------------------------------------------------------------*/
143 static NPT_Result
144 TranslateHResult(HResult result)
146 switch (HRESULT_FACILITY(result.Value)) {
147 case FACILITY_WIN32:
148 switch (HRESULT_CODE(result.Value)) {
149 case WSAHOST_NOT_FOUND:
150 return NPT_ERROR_HOST_UNKNOWN;
152 case WSAETIMEDOUT:
153 return NPT_ERROR_TIMEOUT;
155 case WSAECONNREFUSED:
156 return NPT_ERROR_CONNECTION_REFUSED;
158 case WSAEWOULDBLOCK:
159 return NPT_ERROR_WOULD_BLOCK;
161 case WSAECONNABORTED:
162 return NPT_ERROR_CONNECTION_ABORTED;
164 case WSAECONNRESET:
165 case WSAENETRESET:
166 return NPT_ERROR_CONNECTION_RESET;
168 case WSAEADDRINUSE:
169 return NPT_ERROR_ADDRESS_IN_USE;
171 case WSAENETDOWN:
172 return NPT_ERROR_NETWORK_DOWN;
174 case WSAENETUNREACH:
175 return NPT_ERROR_NETWORK_UNREACHABLE;
177 case WSAEINTR:
178 return NPT_ERROR_INTERRUPTED;
180 case WSAENOTCONN:
181 return NPT_ERROR_NOT_CONNECTED;
183 default:
184 return NPT_FAILURE;
186 break;
188 /* TODO: map error codes */
189 default:
190 return NPT_FAILURE;
194 /*----------------------------------------------------------------------
195 | WaitForAsyncAction
196 +---------------------------------------------------------------------*/
197 static NPT_Result
198 WaitForAsyncAction(IAsyncAction^ action,
199 HANDLE wait_event,
200 DWORD timeout = INFINITE)
202 NPT_Result result = NPT_ERROR_INTERNAL;
204 NPT_LOG_FINEST("waiting for async action...");
205 ResetEvent(wait_event);
207 action->Completed = ref new AsyncActionCompletedHandler
208 ([&](IAsyncAction^ action_, AsyncStatus status) {
209 switch (status) {
210 case AsyncStatus::Canceled:
211 result = NPT_ERROR_TIMEOUT;
212 break;
214 case AsyncStatus::Completed:
215 result = NPT_SUCCESS;
216 break;
218 case AsyncStatus::Error:
219 NPT_LOG_FINE_1("AsyncAction error %x", action_->ErrorCode.Value);
220 result = TranslateHResult(action_->ErrorCode);
221 break;
223 default:
224 result = NPT_ERROR_INTERNAL;
225 break;
227 SetEvent(wait_event);
230 DWORD wait_result = WaitForSingleObjectEx(wait_event, timeout, FALSE);
231 if (wait_result != WAIT_OBJECT_0) {
232 NPT_LOG_FINE("action timed out, canceling...");
233 action->Cancel();
234 WaitForSingleObjectEx(wait_event, INFINITE, FALSE);
236 NPT_LOG_FINEST("done waiting for async action");
238 return result;
241 /*----------------------------------------------------------------------
242 | WaitForAsyncOperation
243 +---------------------------------------------------------------------*/
244 static NPT_Result
245 WaitForAsyncOperation(IAsyncOperation<unsigned int>^ operation,
246 HANDLE wait_event,
247 unsigned int& return_value,
248 DWORD timeout = INFINITE)
250 NPT_Result result = NPT_ERROR_INTERNAL;
252 NPT_LOG_FINEST("waiting for async operation...");
253 return_value = 0;
254 ResetEvent(wait_event);
256 operation->Completed = ref new AsyncOperationCompletedHandler<unsigned int>
257 ([&](IAsyncOperation<unsigned int>^ operation_, AsyncStatus status) {
258 switch (status) {
259 case AsyncStatus::Canceled:
260 result = NPT_ERROR_TIMEOUT;
261 break;
263 case AsyncStatus::Completed:
264 return_value = operation_->GetResults();
265 result = NPT_SUCCESS;
266 break;
268 case AsyncStatus::Error:
269 NPT_LOG_FINE_1("AsyncOperation error %x", operation_->ErrorCode.Value);
270 result = TranslateHResult(operation_->ErrorCode);
271 break;
273 default:
274 result = NPT_ERROR_INTERNAL;
275 break;
277 operation_->Close();
278 SetEvent(wait_event);
281 DWORD wait_result = WaitForSingleObjectEx(wait_event, timeout, FALSE);
282 if (wait_result != WAIT_OBJECT_0) {
283 NPT_LOG_FINE("operation timed out, canceling...");
284 operation->Cancel();
285 WaitForSingleObjectEx(wait_event, INFINITE, FALSE);
287 NPT_LOG_FINEST("done waiting for async operation");
289 return result;
292 /*----------------------------------------------------------------------
293 | NPT_WinRtSocketInputStream::NPT_WinRtSocketInputStream
294 +---------------------------------------------------------------------*/
295 NPT_WinRtSocketInputStream::NPT_WinRtSocketInputStream(StreamSocket^ socket,
296 NPT_Timeout timeout) :
297 m_Socket(socket),
298 m_Timeout(timeout)
300 m_InputStream = socket->InputStream;
301 m_Reader = ref new DataReader(m_InputStream);
302 m_Reader->InputStreamOptions = InputStreamOptions::Partial;
303 m_WaitEvent = CreateEventExW(NULL, L"", 0, EVENT_ALL_ACCESS);
306 /*----------------------------------------------------------------------
307 | NPT_WinRtSocketInputStream::~NPT_WinRtSocketInputStream
308 +---------------------------------------------------------------------*/
309 NPT_WinRtSocketInputStream::~NPT_WinRtSocketInputStream()
311 m_Reader->DetachStream();
312 CloseHandle(m_WaitEvent);
315 /*----------------------------------------------------------------------
316 | NPT_WinRtSocketInputStream::Read
317 +---------------------------------------------------------------------*/
318 NPT_Result
319 NPT_WinRtSocketInputStream::Read(void* buffer,
320 NPT_Size bytes_to_read,
321 NPT_Size* bytes_read)
323 // init and shortcut
324 if (bytes_read) *bytes_read = 0;
325 if (bytes_to_read == 0) return NPT_SUCCESS;
327 NPT_LOG_FINER_1("reading %d bytes", bytes_to_read);
328 auto operation = m_Reader->LoadAsync(bytes_to_read);
330 unsigned int return_value = 0;
331 NPT_Result result = WaitForAsyncOperation(operation, m_WaitEvent, return_value, m_Timeout);
333 if (NPT_SUCCEEDED(result)) {
334 if (return_value) {
335 unsigned int bytes_available = m_Reader->UnconsumedBufferLength;
336 Array<unsigned char>^ bytes = ref new Array<unsigned char>(bytes_available);
337 m_Reader->ReadBytes(bytes);
338 NPT_CopyMemory(buffer, bytes->Data, bytes_available);
339 if (bytes_read) *bytes_read = bytes_available;
340 return NPT_SUCCESS;
341 } else {
342 return NPT_ERROR_EOS;
346 return result;
349 /*----------------------------------------------------------------------
350 | NPT_WinRtSocketInputStream::Seek
351 +---------------------------------------------------------------------*/
352 NPT_Result
353 NPT_WinRtSocketInputStream::Seek(NPT_Position offset)
355 return NPT_ERROR_NOT_SUPPORTED;
358 /*----------------------------------------------------------------------
359 | NPT_WinRtSocketInputStream::Tell
360 +---------------------------------------------------------------------*/
361 NPT_Result
362 NPT_WinRtSocketInputStream::Tell(NPT_Position& where)
364 where = 0;
365 return NPT_ERROR_NOT_SUPPORTED;
368 /*----------------------------------------------------------------------
369 | NPT_WinRtSocketInputStream::GetSize
370 +---------------------------------------------------------------------*/
371 NPT_Result
372 NPT_WinRtSocketInputStream::GetSize(NPT_LargeSize& size)
374 size = 0;
375 return NPT_ERROR_NOT_SUPPORTED;
378 /*----------------------------------------------------------------------
379 | NPT_WinRtSocketInputStream::GetAvailable
380 +---------------------------------------------------------------------*/
381 NPT_Result
382 NPT_WinRtSocketInputStream::GetAvailable(NPT_LargeSize& available)
384 available = 0;
385 return NPT_SUCCESS;
388 /*----------------------------------------------------------------------
389 | NPT_WinRtSocketOutputStream::NPT_WinRtSocketOutputStream
390 +---------------------------------------------------------------------*/
391 NPT_WinRtSocketOutputStream::NPT_WinRtSocketOutputStream(StreamSocket^ socket,
392 NPT_Timeout timeout) :
393 m_Socket(socket),
394 m_Timeout(timeout)
396 m_OutputStream = socket->OutputStream;
397 m_Writer = ref new DataWriter(m_OutputStream);
398 m_WaitEvent = CreateEventExW(NULL, L"", 0, EVENT_ALL_ACCESS);
401 /*----------------------------------------------------------------------
402 | NPT_WinRtSocketOutputStream::~NPT_WinRtSocketOutputStream
403 +---------------------------------------------------------------------*/
404 NPT_WinRtSocketOutputStream::~NPT_WinRtSocketOutputStream()
406 m_Writer->DetachStream();
407 CloseHandle(m_WaitEvent);
410 /*----------------------------------------------------------------------
411 | NPT_WinRtSocketOutputStream::Write
412 +---------------------------------------------------------------------*/
413 NPT_Result
414 NPT_WinRtSocketOutputStream::Write(const void* buffer,
415 NPT_Size bytes_to_write,
416 NPT_Size* bytes_written)
418 NPT_LOG_FINER_1("writing %d bytes", bytes_to_write);
420 Array<unsigned char>^ bytes = ref new Array<unsigned char>(bytes_to_write);
421 NPT_CopyMemory(bytes->Data, buffer, bytes_to_write);
422 m_Writer->WriteBytes(bytes);
423 auto operation = m_Writer->StoreAsync();
424 unsigned int return_value = 0;
426 NPT_Result result = WaitForAsyncOperation(operation, m_WaitEvent, return_value, m_Timeout);
427 if (bytes_written) *bytes_written = return_value;
429 return NPT_SUCCESS;
432 /*----------------------------------------------------------------------
433 | NPT_WinRtSocketOutputStream::Seek
434 +---------------------------------------------------------------------*/
435 NPT_Result
436 NPT_WinRtSocketOutputStream::Seek(NPT_Position offset)
438 return NPT_ERROR_NOT_SUPPORTED;
441 /*----------------------------------------------------------------------
442 | NPT_WinRtSocketOutputStream::Tell
443 +---------------------------------------------------------------------*/
444 NPT_Result
445 NPT_WinRtSocketOutputStream::Tell(NPT_Position& where)
447 where = 0;
448 return NPT_ERROR_NOT_SUPPORTED;
451 /*----------------------------------------------------------------------
452 | NPT_WinRtSocketOutputStream
453 +---------------------------------------------------------------------*/
454 NPT_Result
455 NPT_WinRtSocketOutputStream::Flush()
457 return NPT_SUCCESS;
460 /*----------------------------------------------------------------------
461 | NPT_WinRtTcpClientSocket::NPT_WinRtTcpClientSocket
462 +---------------------------------------------------------------------*/
463 NPT_WinRtTcpClientSocket::NPT_WinRtTcpClientSocket() :
464 m_ReadTimeout(NPT_WINRT_SOCKET_DEFAULT_READ_TIMEOUT),
465 m_WriteTimeout(NPT_WINRT_SOCKET_DEFAULT_WRITE_TIMEOUT)
467 m_Socket = ref new StreamSocket();
468 m_WaitEvent = CreateEventExW(NULL, L"", 0, EVENT_ALL_ACCESS);
471 /*----------------------------------------------------------------------
472 | NPT_WinRtTcpClientSocket::NPT_WinRtTcpClientSocket
473 +---------------------------------------------------------------------*/
474 NPT_WinRtTcpClientSocket::~NPT_WinRtTcpClientSocket()
476 CloseHandle(m_WaitEvent);
479 /*----------------------------------------------------------------------
480 | NPT_WinRtTcpClientSocket::Bind
481 +---------------------------------------------------------------------*/
482 NPT_Result
483 NPT_WinRtTcpClientSocket::Bind(const NPT_SocketAddress& address, bool reuse_address)
485 return NPT_ERROR_NOT_IMPLEMENTED;
488 /*----------------------------------------------------------------------
489 | NPT_WinRtTcpClientSocket::Connect
490 +---------------------------------------------------------------------*/
491 NPT_Result
492 NPT_WinRtTcpClientSocket::Connect(const NPT_SocketAddress& address, NPT_Timeout timeout)
494 try {
495 NPT_LOG_FINE_1("connecting to %s", address.GetIpAddress().m_HostName.GetChars());
497 m_RemoteHostName = ref new HostName(StringFromUTF8(address.GetIpAddress().m_HostName.GetChars()));
498 String^ remote_service = ref new String();
499 NPT_String port = NPT_String::FromIntegerU(address.GetPort());
500 IAsyncAction^ connection = m_Socket->ConnectAsync(m_RemoteHostName, StringFromUTF8(port.GetChars()));
502 // wait for the connection to be established
503 NPT_Result result = WaitForAsyncAction(connection, m_WaitEvent, timeout);
504 if (NPT_FAILED(result)) {
505 NPT_LOG_FINE_1("connection failed (%d)", result);
506 } else {
507 NPT_LOG_FINE("connected");
509 return result;
510 } catch (Exception^ e) {
511 NPT_LOG_FINE("exception caught");
512 return NPT_FAILURE;
516 /*----------------------------------------------------------------------
517 | NPT_WinRtTcpClientSocket::GetInputStream
518 +---------------------------------------------------------------------*/
519 NPT_Result
520 NPT_WinRtTcpClientSocket::GetInputStream(NPT_InputStreamReference& stream)
522 stream = new NPT_WinRtSocketInputStream(m_Socket, m_ReadTimeout);
523 return NPT_SUCCESS;
526 /*----------------------------------------------------------------------
527 | NPT_WinRtTcpClientSocket::GetOutputStream
528 +---------------------------------------------------------------------*/
529 NPT_Result
530 NPT_WinRtTcpClientSocket::GetOutputStream(NPT_OutputStreamReference& stream)
532 stream = new NPT_WinRtSocketOutputStream(m_Socket, m_WriteTimeout);
533 return NPT_SUCCESS;
536 /*----------------------------------------------------------------------
537 | NPT_WinRtTcpClientSocket::GetInfo
538 +---------------------------------------------------------------------*/
539 NPT_Result
540 NPT_WinRtTcpClientSocket::GetInfo(NPT_SocketInfo& info)
542 return NPT_SUCCESS;
545 /*----------------------------------------------------------------------
546 | NPT_WinRtTcpClientSocket::SetReadTimeout
547 +---------------------------------------------------------------------*/
548 NPT_Result
549 NPT_WinRtTcpClientSocket::SetReadTimeout(NPT_Timeout timeout)
551 m_ReadTimeout = timeout;
552 return NPT_SUCCESS;
555 /*----------------------------------------------------------------------
556 | NPT_WinRtTcpClientSocket::SetWriteTimeout
557 +---------------------------------------------------------------------*/
558 NPT_Result
559 NPT_WinRtTcpClientSocket::SetWriteTimeout(NPT_Timeout timeout)
561 m_WriteTimeout = timeout;
562 return NPT_SUCCESS;
565 /*----------------------------------------------------------------------
566 | NPT_WinRtTcpClientSocket::Cancel
567 +---------------------------------------------------------------------*/
568 NPT_Result
569 NPT_WinRtTcpClientSocket::Cancel(bool shutdown)
571 return NPT_SUCCESS;
574 /*----------------------------------------------------------------------
575 | NPT_Socket::~NPT_Socket
576 +---------------------------------------------------------------------*/
577 NPT_Socket::~NPT_Socket()
579 delete m_SocketDelegate;
582 /*----------------------------------------------------------------------
583 | NPT_UdpSocket::NPT_UdpSocket
584 +---------------------------------------------------------------------*/
585 NPT_UdpSocket::NPT_UdpSocket(NPT_Flags flags)
587 m_SocketDelegate = NULL;
588 m_UdpSocketDelegate = NULL;
591 /*----------------------------------------------------------------------
592 | NPT_UdpSocket::NPT_UdpSocket
593 +---------------------------------------------------------------------*/
594 NPT_UdpSocket::NPT_UdpSocket(NPT_UdpSocketInterface* delegate) :
595 m_UdpSocketDelegate(delegate)
599 /*----------------------------------------------------------------------
600 | NPT_UdpSocket::~NPT_UdpSocket
601 +---------------------------------------------------------------------*/
602 NPT_UdpSocket::~NPT_UdpSocket()
604 m_UdpSocketDelegate = NULL;
605 m_SocketDelegate = NULL;
608 /*----------------------------------------------------------------------
609 | NPT_UdpMulticastSocket::NPT_UdpMulticastSocket
610 +---------------------------------------------------------------------*/
611 NPT_UdpMulticastSocket::NPT_UdpMulticastSocket(NPT_Flags flags) :
612 NPT_UdpSocket((NPT_UdpSocketInterface*)0)
614 m_SocketDelegate = NULL;
615 m_UdpSocketDelegate = NULL;
616 m_UdpMulticastSocketDelegate = NULL;
619 /*----------------------------------------------------------------------
620 | NPT_UdpMulticastSocket::~NPT_UdpMulticastSocket
621 +---------------------------------------------------------------------*/
622 NPT_UdpMulticastSocket::~NPT_UdpMulticastSocket()
624 m_SocketDelegate = NULL;
625 m_UdpSocketDelegate = NULL;
626 m_UdpMulticastSocketDelegate = NULL;
629 /*----------------------------------------------------------------------
630 | NPT_TcpClientSocket::NPT_TcpClientSocket
631 +---------------------------------------------------------------------*/
632 NPT_TcpClientSocket::NPT_TcpClientSocket(NPT_Flags flags) :
633 NPT_Socket(NULL)
635 m_SocketDelegate = new NPT_WinRtTcpClientSocket();
638 /*----------------------------------------------------------------------
639 | NPT_TcpClientSocket::NPT_TcpClientSocket
640 +---------------------------------------------------------------------*/
641 NPT_TcpClientSocket::~NPT_TcpClientSocket()
643 delete m_SocketDelegate;
645 m_SocketDelegate = NULL;
648 /*----------------------------------------------------------------------
649 | NPT_TcpServerSocket::NPT_TcpServerSocket
650 +---------------------------------------------------------------------*/
651 NPT_TcpServerSocket::NPT_TcpServerSocket(NPT_Flags flags)
653 m_SocketDelegate = NULL;
654 m_TcpServerSocketDelegate = NULL;
657 /*----------------------------------------------------------------------
658 | NPT_TcpServerSocket::NPT_TcpServerSocket
659 +---------------------------------------------------------------------*/
660 NPT_TcpServerSocket::~NPT_TcpServerSocket()
662 m_SocketDelegate = NULL;
663 m_TcpServerSocketDelegate = NULL;