1- using Microsoft . Extensions . Logging ;
21using System ;
32using System . Collections . Generic ;
43using System . Net . Sockets ;
54using System . Threading ;
5+ using Microsoft . Extensions . Logging ;
66using ThreeByte . LinkLib . Shared . Logging ;
77
88namespace ThreeByte . LinkLib . TcpLink
99{
1010 public class AsyncTcpLink : IDisposable
1111 {
12- public event EventHandler < bool > ? IsConnectedChanged ;
13- public event EventHandler < bool > ? IsEnabledChanged ;
14- public event EventHandler < Exception > ? ErrorOccurred ;
15- public event EventHandler ? DataReceived ;
16- public bool IsConnected => _isConnected ;
17- public bool IsEnabled => _isEnabled ;
18- public string Address => _settings . Address ;
19- public int Port => _settings . Port ;
20- public bool HasData => _incomingData . Count > 0 ;
21-
2212 private const int BufferSize = 8092 ;
2313 private const int MaxDataSize = 100 ;
24-
25- private readonly TcpLinkSettings _settings ;
2614 private readonly ILogger _logger ;
2715
28- private bool _isEnabled = true ;
29- private bool _isDisposed = false ;
30- private bool _isConnected = false ;
31- private List < byte [ ] > _incomingData = new List < byte [ ] > ( ) ;
32- private object _clientLock = new object ( ) ;
16+ private readonly TcpLinkSettings _settings ;
17+ private readonly object _clientLock = new object ( ) ;
3318 private IAsyncResult ? _connectResult ;
19+ private readonly List < byte [ ] > _incomingData = new List < byte [ ] > ( ) ;
20+ private bool _isDisposed ;
21+
22+ private NetworkStream ? _networkStream ;
3423 private IAsyncResult ? _readResult ;
35- private IAsyncResult ? _writeResult ;
3624
3725 private TcpClient ? _tcpClient ;
38- private NetworkStream ? _networkStream ;
26+ private IAsyncResult ? _writeResult ;
3927
4028 public AsyncTcpLink ( string address , int port )
4129 : this ( address , port , true )
@@ -45,7 +33,7 @@ public AsyncTcpLink(string address, int port)
4533 public AsyncTcpLink ( string address , int port , bool enabled = true )
4634 {
4735 _settings = new TcpLinkSettings ( address , port ) ;
48- _isEnabled = enabled ;
36+ IsEnabled = enabled ;
4937 _logger = LogFactory . Create < AsyncTcpLink > ( ) ;
5038
5139 if ( enabled )
@@ -54,19 +42,49 @@ public AsyncTcpLink(string address, int port, bool enabled = true)
5442 }
5543 }
5644
45+ public bool IsConnected { get ; private set ; }
46+
47+ public bool IsEnabled { get ; private set ; } = true ;
48+
49+ public string Address => _settings . Address ;
50+ public int Port => _settings . Port ;
51+ public bool HasData => _incomingData . Count > 0 ;
52+
53+ /// <summary>
54+ /// Cancels the thread and releases resources.
55+ /// Clients of this class are responsible for calling it.
56+ /// </summary>
57+ public void Dispose ( )
58+ {
59+ if ( _isDisposed )
60+ {
61+ return ;
62+ }
63+
64+ _isDisposed = true ;
65+ _logger . LogInformation ( "Cleaning up network resources." ) ;
66+
67+ SafeClose ( ) ;
68+ }
69+
70+ public event EventHandler < bool > ? IsConnectedChanged ;
71+ public event EventHandler < bool > ? IsEnabledChanged ;
72+ public event EventHandler < Exception > ? ErrorOccurred ;
73+ public event EventHandler ? DataReceived ;
74+
5775 /// <summary>
58- /// Sets a value indicating whether messages should be propagated to the network or not
76+ /// Sets a value indicating whether messages should be propagated to the network or not
5977 /// </summary>
6078 /// <param name="value"></param>
6179 public void SetEnabled ( bool value )
6280 {
63- _isEnabled = value ;
81+ IsEnabled = value ;
6482
65- if ( ! _isEnabled )
83+ if ( ! IsEnabled )
6684 {
6785 SafeClose ( ) ;
6886 }
69- else if ( ! _isConnected )
87+ else if ( ! IsConnected )
7088 {
7189 SafeConnect ( ) ;
7290 }
@@ -75,12 +93,12 @@ public void SetEnabled(bool value)
7593 }
7694
7795 /// <summary>
78- /// Asynchronously sends the TCP message, waiting until the connection is reestablihsed if necessary
96+ /// Asynchronously sends the TCP message, waiting until the connection is reestablihsed if necessary
7997 /// </summary>
8098 /// <param name="message">binary message to be sent</param>
8199 public void SendMessage ( byte [ ] message )
82100 {
83- if ( ! _isEnabled )
101+ if ( ! IsEnabled )
84102 {
85103 return ;
86104 }
@@ -111,24 +129,7 @@ public void SendMessage(byte[] message)
111129 }
112130
113131 /// <summary>
114- /// Cancels the thread and releases resources.
115- /// Clients of this class are responsible for calling it.
116- /// </summary>
117- public void Dispose ( )
118- {
119- if ( _isDisposed )
120- {
121- return ;
122- }
123-
124- _isDisposed = true ;
125- _logger . LogInformation ( "Cleaning up network resources." ) ;
126-
127- SafeClose ( ) ;
128- }
129-
130- /// <summary>
131- /// Very carefully checks and shuts down the tcpClient and sets it to null
132+ /// Very carefully checks and shuts down the tcpClient and sets it to null
132133 /// </summary>
133134 private void SafeClose ( )
134135 {
@@ -175,7 +176,7 @@ private void SafeConnect(object state)
175176 }
176177
177178 /// <summary>
178- /// Carefully check to see if the link is connected or can be reestablished
179+ /// Carefully check to see if the link is connected or can be reestablished
179180 /// </summary>
180181 private void SafeConnect ( )
181182 {
@@ -236,7 +237,8 @@ private void ConnectCallback(IAsyncResult asyncResult)
236237 {
237238 ChangeIsConnected ( false ) ;
238239 }
239- if ( ! _isEnabled )
240+
241+ if ( ! IsEnabled )
240242 {
241243 SafeClose ( ) ;
242244 }
@@ -252,9 +254,9 @@ private void ConnectCallback(IAsyncResult asyncResult)
252254 _logger . LogDebug ( "Clearing Connect Result." ) ;
253255 _connectResult = null ;
254256
255- if ( _isEnabled )
257+ if ( IsEnabled )
256258 {
257- if ( ! _isConnected )
259+ if ( ! IsConnected )
258260 {
259261 Timer timer = new Timer (
260262 SafeConnect ,
@@ -296,7 +298,7 @@ private void WriteCallback(IAsyncResult asyncResult)
296298
297299 private void ReceiveData ( )
298300 {
299- if ( ! _isEnabled )
301+ if ( ! IsEnabled )
300302 {
301303 return ;
302304 }
@@ -362,7 +364,6 @@ private void ReadCallback(IAsyncResult asyncResult)
362364
363365 ChangeIsConnected ( true ) ;
364366 }
365-
366367 }
367368 catch ( Exception ex )
368369 {
@@ -386,16 +387,46 @@ private void ReadCallback(IAsyncResult asyncResult)
386387 ReceiveData ( ) ;
387388 }
388389
390+ /// <summary>
391+ /// Fetches and removes (pops) the next available group of bytes as received on this link in order (FIFO)
392+ /// </summary>
393+ /// <returns>null if the link is not Enabled or there is no data currently queued to return, an array of bytes otherwise.</returns>
394+ public byte [ ] GetMessage ( )
395+ {
396+ if ( _isDisposed )
397+ {
398+ throw new ObjectDisposedException ( "Cannot get message from disposed NetworkLink" ) ;
399+ }
400+
401+ //Return null if the link is not enabled
402+ if ( IsEnabled )
403+ {
404+ return null ;
405+ }
406+
407+ byte [ ] newMessage = null ;
408+ lock ( _incomingData )
409+ {
410+ if ( HasData )
411+ {
412+ newMessage = _incomingData [ 0 ] ;
413+ _incomingData . RemoveAt ( 0 ) ;
414+ }
415+ }
416+
417+ return newMessage ;
418+ }
419+
389420 private void ChangeIsConnected ( bool value )
390421 {
391- _isConnected = value ;
422+ IsConnected = value ;
392423 IsConnectedChanged ? . Invoke ( this , value ) ;
393424 }
394425
395426 private void HandleError ( Exception ex , string message )
396427 {
397- _logger . LogError ( exception : ex , message : message ) ;
428+ _logger . LogError ( ex , message ) ;
398429 ErrorOccurred ? . Invoke ( this , ex ) ;
399430 }
400431 }
401- }
432+ }
0 commit comments