@@ -74,6 +74,11 @@ internal Connection(string url, int delay, IConnectionTransport transport, ILogg
7474 /// <value><c>true</c> if is closed; otherwise, <c>false</c>.</value>
7575 public bool IsClosed { get ; internal set ; }
7676
77+ /// <summary>
78+ /// Connection close reason.
79+ /// </summary>
80+ public string CloseReason { get ; private set ; }
81+
7782 /// <summary>
7883 /// Gets the logger factory.
7984 /// </summary>
@@ -88,7 +93,7 @@ internal async Task<JObject> SendAsync(string method, dynamic args = null, bool
8893 {
8994 if ( IsClosed )
9095 {
91- throw new TargetClosedException ( $ "Protocol error({ method } ): Target closed.") ;
96+ throw new TargetClosedException ( $ "Protocol error({ method } ): Target closed.", CloseReason ) ;
9297 }
9398
9499 var id = Interlocked . Increment ( ref _lastId ) ;
@@ -137,27 +142,29 @@ internal async Task<CDPSession> CreateSessionAsync(TargetInfo targetInfo)
137142 internal bool HasPendingCallbacks ( ) => _callbacks . Count != 0 ;
138143 #endregion
139144
140- private void OnClose ( )
145+ internal void Close ( string closeReason )
141146 {
142147 if ( IsClosed )
143148 {
144149 return ;
145150 }
146151 IsClosed = true ;
152+ CloseReason = closeReason ;
147153
148154 Transport . StopReading ( ) ;
149155 Closed ? . Invoke ( this , new EventArgs ( ) ) ;
150156
151157 foreach ( var session in _sessions . Values . ToArray ( ) )
152158 {
153- session . OnClosed ( ) ;
159+ session . Close ( closeReason ) ;
154160 }
155161 _sessions . Clear ( ) ;
156162
157163 foreach ( var response in _callbacks . Values . ToArray ( ) )
158164 {
159165 response . TaskWrapper . TrySetException ( new TargetClosedException (
160- $ "Protocol error({ response . Method } ): Target closed."
166+ $ "Protocol error({ response . Method } ): Target closed.",
167+ closeReason
161168 ) ) ;
162169 }
163170 _callbacks . Clear ( ) ;
@@ -176,77 +183,86 @@ internal static IConnection FromSession(CDPSession session)
176183
177184 private async void Transport_MessageReceived ( object sender , MessageReceivedEventArgs e )
178185 {
179- var response = e . Message ;
180- JObject obj = null ;
181-
182- if ( response . Length > 0 && Delay > 0 )
183- {
184- await Task . Delay ( Delay ) . ConfigureAwait ( false ) ;
185- }
186-
187186 try
188187 {
189- obj = JObject . Parse ( response ) ;
190- }
191- catch ( JsonException exc )
192- {
193- _logger . LogError ( exc , "Failed to deserialize response" , response ) ;
194- return ;
195- }
196-
197- _logger . LogTrace ( "◀ Receive {Message}" , response ) ;
198-
199- var id = obj [ MessageKeys . Id ] ? . Value < int > ( ) ;
188+ var response = e . Message ;
189+ JObject obj = null ;
200190
201- if ( id . HasValue )
202- {
203- //If we get the object we are waiting for we return if
204- //if not we add this to the list, sooner or later some one will come for it
205- if ( _callbacks . TryRemove ( id . Value , out var callback ) )
191+ if ( response . Length > 0 && Delay > 0 )
206192 {
207- if ( obj [ MessageKeys . Error ] != null )
208- {
209- callback . TaskWrapper . TrySetException ( new MessageException ( callback , obj ) ) ;
210- }
211- else
212- {
213- callback . TaskWrapper . TrySetResult ( obj [ MessageKeys . Result ] . Value < JObject > ( ) ) ;
214- }
193+ await Task . Delay ( Delay ) . ConfigureAwait ( false ) ;
215194 }
216- }
217- else
218- {
219- var method = obj [ MessageKeys . Method ] . AsString ( ) ;
220- var param = obj [ MessageKeys . Params ] ;
221195
222- if ( method == "Target.receivedMessageFromTarget" )
196+ try
223197 {
224- var sessionId = param [ MessageKeys . SessionId ] . AsString ( ) ;
225- if ( _sessions . TryGetValue ( sessionId , out var session ) )
226- {
227- session . OnMessage ( param [ MessageKeys . Message ] . AsString ( ) ) ;
228- }
198+ obj = JObject . Parse ( response ) ;
229199 }
230- else if ( method == "Target.detachedFromTarget" )
200+ catch ( JsonException exc )
201+ {
202+ _logger . LogError ( exc , "Failed to deserialize response" , response ) ;
203+ return ;
204+ }
205+
206+ _logger . LogTrace ( "◀ Receive {Message}" , response ) ;
207+
208+ var id = obj [ MessageKeys . Id ] ? . Value < int > ( ) ;
209+
210+ if ( id . HasValue )
231211 {
232- var sessionId = param [ MessageKeys . SessionId ] . AsString ( ) ;
233- if ( _sessions . TryRemove ( sessionId , out var session ) && ! session . IsClosed )
212+ //If we get the object we are waiting for we return if
213+ //if not we add this to the list, sooner or later some one will come for it
214+ if ( _callbacks . TryRemove ( id . Value , out var callback ) )
234215 {
235- session . OnClosed ( ) ;
216+ if ( obj [ MessageKeys . Error ] != null )
217+ {
218+ callback . TaskWrapper . TrySetException ( new MessageException ( callback , obj ) ) ;
219+ }
220+ else
221+ {
222+ callback . TaskWrapper . TrySetResult ( obj [ MessageKeys . Result ] . Value < JObject > ( ) ) ;
223+ }
236224 }
237225 }
238226 else
239227 {
240- MessageReceived ? . Invoke ( this , new MessageEventArgs
228+ var method = obj [ MessageKeys . Method ] . AsString ( ) ;
229+ var param = obj [ MessageKeys . Params ] ;
230+
231+ if ( method == "Target.receivedMessageFromTarget" )
232+ {
233+ var sessionId = param [ MessageKeys . SessionId ] . AsString ( ) ;
234+ if ( _sessions . TryGetValue ( sessionId , out var session ) )
235+ {
236+ session . OnMessage ( param [ MessageKeys . Message ] . AsString ( ) ) ;
237+ }
238+ }
239+ else if ( method == "Target.detachedFromTarget" )
241240 {
242- MessageID = method ,
243- MessageData = param
244- } ) ;
241+ var sessionId = param [ MessageKeys . SessionId ] . AsString ( ) ;
242+ if ( _sessions . TryRemove ( sessionId , out var session ) && ! session . IsClosed )
243+ {
244+ session . Close ( "Target.detachedFromTarget" ) ;
245+ }
246+ }
247+ else
248+ {
249+ MessageReceived ? . Invoke ( this , new MessageEventArgs
250+ {
251+ MessageID = method ,
252+ MessageData = param
253+ } ) ;
254+ }
245255 }
246256 }
257+ catch ( Exception ex )
258+ {
259+ var message = $ "Connection failed to process { e . Message } . { ex . Message } . { ex . StackTrace } ";
260+ _logger . LogError ( ex , message ) ;
261+ Close ( message ) ;
262+ }
247263 }
248264
249- void Transport_Closed ( object sender , EventArgs e ) => OnClose ( ) ;
265+ void Transport_Closed ( object sender , TransportClosedEventArgs e ) => Close ( e . CloseReason ) ;
250266
251267 #endregion
252268
@@ -290,7 +306,7 @@ internal static async Task<Connection> Create(string url, IConnectionOptions con
290306 /// <see cref="Connection"/> was occupying.</remarks>
291307 public void Dispose ( )
292308 {
293- OnClose ( ) ;
309+ Close ( "Connection disposed" ) ;
294310 Transport . Dispose ( ) ;
295311 }
296312 #endregion
@@ -301,6 +317,7 @@ public void Dispose()
301317 Task < JObject > IConnection . SendAsync ( string method , dynamic args , bool waitForCallback )
302318 => SendAsync ( method , args , waitForCallback ) ;
303319 IConnection IConnection . Connection => null ;
320+ void IConnection . Close ( string closeReason ) => Close ( closeReason ) ;
304321 #endregion
305322 }
306323}
0 commit comments