3
3
using Microsoft . Extensions . Logging ;
4
4
using Microsoft . Extensions . Options ;
5
5
using RemotePythonExecution . Interface . RemotePythonExecutionServiceDependency . JsonModel ;
6
+ using SimpleUdp ;
6
7
using System ;
7
8
using System . Collections . Generic ;
8
9
using System . Diagnostics ;
9
10
using System . IO ;
10
- using System . Net . Sockets ;
11
+ using System . Linq ;
11
12
using System . Runtime . InteropServices ;
12
13
using System . Text ;
13
14
using System . Threading ;
@@ -30,16 +31,18 @@ public class RemotePythonExecutionService : BackgroundService, IHostedService
30
31
31
32
private WatsonTcpServer mTcpServer ;
32
33
private Process mProcess ;
33
- public Guid CurrentConnectionGuid ;
34
+ private UdpEndpoint mUdpEndpoint ;
35
+ private ( Guid Guid , string ip ) mCurrentClientParam ;
36
+
34
37
private bool mIsDisposed ;
35
38
36
39
private string mInterpreterPath = string . Empty ;
37
40
private string mWorkingDirrectoryPath = string . Empty ;
38
41
private string mSourceCodeSavePath = string . Empty ;
39
42
40
- private bool mIsProcessEnded = false ;
41
43
private bool mIsOutputEnded = false ;
42
44
45
+
43
46
#endregion
44
47
45
48
#region ~
@@ -56,11 +59,13 @@ public RemotePythonExecutionService(IServiceProvider serviceProvider)
56
59
SetPath ( mAppSettingsMonitor . CurrentValue ) ;
57
60
58
61
mTcpServer = new WatsonTcpServer ( Ip , Port ) ;
62
+ mUdpEndpoint = new UdpEndpoint ( Ip , Port ) ;
63
+
59
64
mAppSettingsMonitor . OnChange ( OnChangeSettings ) ;
60
65
61
66
Subscribe ( ) ;
62
67
mTcpServer . Start ( ) ;
63
- mLogger . LogInformation ( "Server runing on {ip}:{port}" , Ip , Port ) ;
68
+ mLogger . LogInformation ( "Servers runing on {ip}:{port}" , Ip , Port ) ;
64
69
}
65
70
66
71
#endregion
@@ -73,6 +78,7 @@ private void Subscribe()
73
78
mTcpServer . Events . ClientDisconnected += ClientDisconnected ;
74
79
mTcpServer . Events . MessageReceived += MessageReceived ;
75
80
mTcpServer . Events . ExceptionEncountered += ExceptionEncountered ;
81
+
76
82
AppDomain . CurrentDomain . ProcessExit += AppProcessExit ;
77
83
78
84
mAppLifetime . ApplicationStopping . Register ( OnStopping ) ;
@@ -84,6 +90,7 @@ private void UnSubscribe()
84
90
mTcpServer . Events . ClientDisconnected -= ClientDisconnected ;
85
91
mTcpServer . Events . MessageReceived -= MessageReceived ;
86
92
mTcpServer . Events . ExceptionEncountered -= ExceptionEncountered ;
93
+
87
94
AppDomain . CurrentDomain . ProcessExit -= AppProcessExit ;
88
95
}
89
96
@@ -98,30 +105,35 @@ private void OnChangeSettings(AppSettings settings, string arg2)
98
105
}
99
106
100
107
private void ClientConnected ( object sender , ConnectionEventArgs e )
101
- {
102
- mLogger . LogInformation ( "Client connected. Connection id: {Guid}" , e . Client . Guid ) ;
103
- CurrentConnectionGuid = e . Client . Guid ;
108
+ {
109
+ var ip = e . Client . IpPort . Split ( ':' ) . FirstOrDefault ( ) ;
110
+ mCurrentClientParam = ( e . Client . Guid , ip ) ;
104
111
105
112
IsOutputEnded = false ;
106
- IsProcessEnded = false ;
113
+ mLogger . LogInformation ( "Client connected. Connection id: {Guid}. Client ip: {ip}" , e . Client . Guid , ip ) ;
107
114
}
108
115
109
116
private void ClientDisconnected ( object sender , DisconnectionEventArgs e )
110
117
{
111
118
mLogger . LogInformation ( "Client disconnected. Connection id: {Guid}" , e . Client . Guid ) ;
112
-
113
119
KillProcess ( ) ;
114
- IsOutputEnded = true ;
115
120
}
116
121
117
122
private void ExceptionEncountered ( object sender , ExceptionEventArgs e )
118
123
{
119
124
if ( e . Exception is IOException )
125
+ {
126
+ mLogger . LogError ( "IOException" ) ;
120
127
return ;
128
+ }
129
+
121
130
122
- if ( e . Exception is SocketException )
131
+ if ( e . Exception is OperationCanceledException )
132
+ {
133
+ mLogger . LogError ( "OperationCanceledException" ) ;
123
134
return ;
124
-
135
+ }
136
+
125
137
mLogger . LogError ( "Error happened {errorMessage}" , e . Exception ) ;
126
138
}
127
139
@@ -166,11 +178,9 @@ private void MessageReceived(object sender, MessageReceivedEventArgs e)
166
178
167
179
case "exit" :
168
180
{
181
+ mLogger . LogInformation ( "Exit by client request" ) ;
169
182
170
- mLogger . LogDebug ( "Exit by client request" ) ;
171
-
172
183
KillProcess ( ) ;
173
- mIsOutputEnded = true ;
174
184
break ;
175
185
}
176
186
}
@@ -183,9 +193,9 @@ private void ProcessErrorDataReceived(object sender, DataReceivedEventArgs e)
183
193
{
184
194
try
185
195
{
186
- mTcpServer . SendAsync ( CurrentConnectionGuid , e . Data ) ;
196
+ mUdpEndpoint . SendAsync ( mCurrentClientParam . ip , Port , e . Data ) ;
187
197
mLogger . LogDebug ( "{data}" , e . Data ) ;
188
- IsOutputEnded = false ;
198
+
189
199
}
190
200
catch ( Exception exp )
191
201
{
@@ -195,20 +205,17 @@ private void ProcessErrorDataReceived(object sender, DataReceivedEventArgs e)
195
205
}
196
206
}
197
207
198
- private async void ProcessOutputDataReceived ( object sender , DataReceivedEventArgs e )
208
+ private void ProcessOutputDataReceived ( object sender , DataReceivedEventArgs e )
199
209
{
200
210
if ( e . Data != null )
201
211
{
202
212
try
203
213
{
204
- await mTcpServer . SendAsync ( CurrentConnectionGuid , e . Data ) ;
214
+ if ( mTcpServer . IsClientConnected ( mCurrentClientParam . Guid ) )
215
+ mUdpEndpoint . SendAsync ( mCurrentClientParam . ip , Port , e . Data ) ;
216
+
205
217
mLogger . LogDebug ( "{data}" , e . Data ) ;
206
218
}
207
- catch ( TaskCanceledException )
208
- {
209
- mLogger . LogError ( "Task was canceled" ) ;
210
- IsOutputEnded = true ;
211
- }
212
219
catch ( Exception exp )
213
220
{
214
221
mLogger . LogError ( "Catch happened {exp}" , exp ) ;
@@ -217,16 +224,14 @@ private async void ProcessOutputDataReceived(object sender, DataReceivedEventArg
217
224
}
218
225
else
219
226
{
220
- mLogger . LogDebug ( "Output ended happened" ) ;
221
- await Task . Delay ( 100 ) ;
227
+ mLogger . LogInformation ( "Output ended happened" ) ;
222
228
IsOutputEnded = true ;
223
229
}
224
230
}
225
231
226
232
private void ProcessExited ( object sender , EventArgs e )
227
233
{
228
- mLogger . LogDebug ( "Process ended happened" ) ;
229
- IsProcessEnded = true ;
234
+ mLogger . LogInformation ( "Process ended happened" ) ;
230
235
}
231
236
232
237
private void AppProcessExit ( object sender , EventArgs e )
@@ -255,11 +260,9 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
255
260
{
256
261
while ( ! stoppingToken . IsCancellationRequested )
257
262
{
258
- while ( IsOutputEnded && IsProcessEnded )
263
+ while ( IsOutputEnded )
259
264
{
260
265
IsOutputEnded = false ;
261
- IsProcessEnded = false ;
262
-
263
266
ExitData exitData = new ( ) ;
264
267
265
268
try
@@ -279,7 +282,6 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
279
282
} ;
280
283
281
284
mProcess . Dispose ( ) ;
282
- mProcess = null ;
283
285
}
284
286
}
285
287
catch ( Exception exception )
@@ -290,13 +292,15 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
290
292
var exitJson = mTcpServer . SerializationHelper . SerializeJson ( exitData ) ;
291
293
var exitDictonary = new Dictionary < string , object > ( ) { { "exitData" , exitJson } } ;
292
294
293
- if ( mTcpServer . IsClientConnected ( CurrentConnectionGuid ) )
295
+ if ( mTcpServer . IsClientConnected ( mCurrentClientParam . Guid ) )
294
296
{
295
- await mTcpServer . SendAsync ( CurrentConnectionGuid , string . Empty , exitDictonary , token : stoppingToken ) ;
296
- await mTcpServer . DisconnectClientAsync ( CurrentConnectionGuid , MessageStatus . Removed , true , stoppingToken ) ;
297
+ mLogger . LogInformation ( "Send exit data" ) ;
298
+ await mTcpServer . SendAsync ( mCurrentClientParam . Guid , string . Empty , exitDictonary , token : stoppingToken ) ;
299
+ await mTcpServer . DisconnectClientAsync ( mCurrentClientParam . Guid , MessageStatus . Removed , true , stoppingToken ) ;
297
300
}
298
-
299
- CurrentConnectionGuid = Guid . Empty ;
301
+
302
+ mCurrentClientParam . Guid = Guid . Empty ;
303
+ mCurrentClientParam . ip = string . Empty ;
300
304
}
301
305
}
302
306
}
@@ -317,20 +321,6 @@ private bool IsOutputEnded
317
321
}
318
322
}
319
323
320
-
321
-
322
- private bool IsProcessEnded
323
- {
324
- get { return mIsProcessEnded ; }
325
- set
326
- {
327
- if ( value == mIsProcessEnded )
328
- return ;
329
-
330
- mIsProcessEnded = value ;
331
- }
332
- }
333
-
334
324
private string InterpreterPath
335
325
{
336
326
get { return mInterpreterPath ; }
@@ -377,7 +367,6 @@ private string SourceCodeSavePath
377
367
mSourceCodeSavePath = value ;
378
368
mLogger . LogDebug ( "New path for {name} register with values {value}" , nameof ( SourceCodeSavePath ) , SourceCodeSavePath ) ;
379
369
}
380
-
381
370
}
382
371
383
372
private string mIp = string . Empty ;
@@ -426,15 +415,19 @@ private int Port
426
415
427
416
private void KillProcess ( )
428
417
{
429
- if ( mProcess == null )
430
- return ;
431
-
432
418
try
433
419
{
434
420
mProcess . CancelErrorRead ( ) ;
435
421
mProcess . CancelOutputRead ( ) ;
436
422
437
423
mProcess . Kill ( entireProcessTree : true ) ;
424
+ mLogger . LogInformation ( "KillProcess(): {id}," , mProcess . Id ) ;
425
+
426
+ IsOutputEnded = true ;
427
+ }
428
+ catch ( InvalidOperationException )
429
+ {
430
+ mLogger . LogError ( "KillProcess(): InvalidOperationException happened" ) ;
438
431
}
439
432
catch ( Exception ex )
440
433
{
@@ -452,17 +445,23 @@ private void OnServerAddressChange()
452
445
if ( mTcpServer . Connections != 0 )
453
446
{
454
447
KillProcess ( ) ;
455
- IsOutputEnded = true ;
456
448
}
457
449
458
450
mTcpServer . Stop ( ) ;
451
+
452
+ mTcpServer . Dispose ( ) ;
453
+ mUdpEndpoint . Dispose ( ) ;
454
+
459
455
UnSubscribe ( ) ;
460
456
}
461
457
462
458
mTcpServer = new WatsonTcpServer ( Ip , Port ) ;
459
+ mUdpEndpoint = new UdpEndpoint ( Ip , Port ) ;
460
+
463
461
Subscribe ( ) ;
464
462
mTcpServer . Start ( ) ;
465
- mLogger . LogInformation ( "Server runing on {ip}:{port}" , Ip , Port ) ;
463
+
464
+ mLogger . LogInformation ( "Servers runing on {ip}:{port}" , Ip , Port ) ;
466
465
}
467
466
468
467
private void SetPath ( AppSettings appSettings )
@@ -519,7 +518,7 @@ private void StartProcess(bool withDebug = false)
519
518
mProcess = new ( )
520
519
{
521
520
StartInfo = proccesInfo ,
522
- EnableRaisingEvents = true ,
521
+ EnableRaisingEvents = true
523
522
} ;
524
523
525
524
mProcess . Exited += ProcessExited ;
@@ -529,7 +528,7 @@ private void StartProcess(bool withDebug = false)
529
528
530
529
mProcess . BeginOutputReadLine ( ) ;
531
530
mProcess . BeginErrorReadLine ( ) ;
532
-
531
+
533
532
mProcess . WaitForExit ( ) ;
534
533
}
535
534
@@ -542,8 +541,6 @@ protected virtual void Dispose(bool disposing)
542
541
if ( disposing )
543
542
{
544
543
KillProcess ( ) ;
545
- IsOutputEnded = true ;
546
-
547
544
UnSubscribe ( ) ;
548
545
mTcpServer . Stop ( ) ;
549
546
mTcpServer . Dispose ( ) ;
0 commit comments