123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- /*
- Copyright (c) 2013, 2014 Paolo Patierno
- All rights reserved. This program and the accompanying materials
- are made available under the terms of the Eclipse Public License v1.0
- and Eclipse Distribution License v1.0 which accompany this distribution.
- The Eclipse Public License is available at
- http://www.eclipse.org/legal/epl-v10.html
- and the Eclipse Distribution License is available at
- http://www.eclipse.org/org/documents/edl-v10.php.
- Contributors:
- Paolo Patierno - initial API and implementation and/or initial documentation
- ----------------------------------------------------------------------------
- Giovanni Paolo Vigano' - preprocessor directives for platform dependent compilation in Unity
- */
- #if ((!UNITY_EDITOR&&UNITY_WSA_10_0&&!ENABLE_IL2CPP))
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Windows.Networking;
- using Windows.Networking.Sockets;
- using System.Runtime.InteropServices.WindowsRuntime;
- using Windows.Storage.Streams;
- using System.Threading;
- namespace uPLibrary.Networking.M2Mqtt
- {
- public class MqttNetworkChannel : IMqttNetworkChannel
- {
- // stream socket for communication
- private StreamSocket socket;
- // remote host information
- private HostName remoteHostName;
- private int remotePort;
- // using SSL
- private bool secure;
- // SSL/TLS protocol version
- private MqttSslProtocols sslProtocol;
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="socket">Socket opened with the client</param>
- public MqttNetworkChannel(StreamSocket socket)
- {
- this.socket = socket;
- this.sslProtocol = MqttSslProtocols.None;
- }
- /// <summary>
- /// Constructor
- /// </summary>
- /// <param name="remoteHostName">Remote Host name</param>
- /// <param name="remotePort">Remote port</param>
- /// <param name="secure">Using SSL</param>
- /// <param name="sslProtocol">SSL/TLS protocol version</param>
- public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, MqttSslProtocols sslProtocol)
- {
- this.remoteHostName = new HostName(remoteHostName);
- this.remotePort = remotePort;
- this.secure = secure;
- this.sslProtocol = sslProtocol;
- if (secure && (sslProtocol == MqttSslProtocols.None))
- throw new ArgumentException("For secure connection, an SSL/TLS protocol version is needed");
- }
- public bool DataAvailable
- {
- get { return true; }
- }
- public int Receive(byte[] buffer)
- {
- IBuffer result;
- // read all data needed (until fill buffer)
- int idx = 0;
- while (idx < buffer.Length)
- {
- // fixed scenario with socket closed gracefully by peer/broker and
- // Read return 0. Avoid infinite loop.
- // read is executed synchronously
- result = this.socket.InputStream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.None).AsTask().Result;
- if (result.Length == 0)
- return 0;
- idx += (int)result.Length;
- }
- return buffer.Length;
- }
- public int Receive(byte[] buffer, int timeout)
- {
- CancellationTokenSource cts = new CancellationTokenSource(timeout);
- try
- {
- IBuffer result;
- // read all data needed (until fill buffer)
- int idx = 0;
- while (idx < buffer.Length)
- {
- // fixed scenario with socket closed gracefully by peer/broker and
- // Read return 0. Avoid infinite loop.
- // read is executed synchronously
- result = this.socket.InputStream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.None).AsTask(cts.Token).Result;
- if (result.Length == 0)
- return 0;
- idx += (int)result.Length;
- }
- return buffer.Length;
- }
- catch (TaskCanceledException)
- {
- return 0;
- }
- }
- public int Send(byte[] buffer)
- {
- // send is executed synchronously
- return (int)this.socket.OutputStream.WriteAsync(buffer.AsBuffer()).AsTask().Result;
- }
- public void Close()
- {
- this.socket.Dispose();
- }
- public void Connect()
- {
- this.socket = new StreamSocket();
- // connection is executed synchronously
- this.socket.ConnectAsync(this.remoteHostName,
- this.remotePort.ToString(),
- MqttSslUtility.ToSslPlatformEnum(this.sslProtocol)).AsTask().Wait();
- }
- public void Accept()
- {
- // TODO : SSL support with StreamSocket / StreamSocketListener seems to be NOT supported
- return;
- }
- }
- /// <summary>
- /// MQTT SSL utility class
- /// </summary>
- public static class MqttSslUtility
- {
- public static SocketProtectionLevel ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
- {
- switch (mqttSslProtocol)
- {
- case MqttSslProtocols.None:
- return SocketProtectionLevel.PlainSocket;
- case MqttSslProtocols.SSLv3:
- return SocketProtectionLevel.SslAllowNullEncryption;
- case MqttSslProtocols.TLSv1_0:
- return SocketProtectionLevel.Tls10;
- case MqttSslProtocols.TLSv1_1:
- return SocketProtectionLevel.Tls11;
- case MqttSslProtocols.TLSv1_2:
- return SocketProtectionLevel.Tls12;
- default:
- throw new ArgumentException("SSL/TLS protocol version not supported");
- }
- }
- }
- }
- #endif
|