22using System . Collections . Generic ;
33using System . Diagnostics ;
44using System . IO ;
5+ using System . IO . Pipes ;
56using System . Linq ;
67using System . Text ;
78using System . Threading ;
@@ -11,9 +12,8 @@ namespace OpenVpn
1112{
1213 class OpenVpnChild
1314 {
14- StreamWriter logFile ;
15+ string logFile ;
1516 Process process ;
16- ProcessStartInfo startInfo ;
1717 System . Timers . Timer restartTimer ;
1818 OpenVpnServiceConfiguration config ;
1919 string configFile ;
@@ -27,43 +27,14 @@ public OpenVpnChild(OpenVpnServiceConfiguration config, string configFile)
2727 * so make sure we are working on a copy */
2828 this . configFile = String . Copy ( configFile ) ;
2929 this . exitEvent = Path . GetFileName ( configFile ) + "_" + Process . GetCurrentProcess ( ) . Id . ToString ( ) ;
30- var justFilename = System . IO . Path . GetFileName ( configFile ) ;
31- var logFilename = config . logDir + "\\ " +
32- justFilename . Substring ( 0 , justFilename . Length - config . configExt . Length ) + ".log" ;
30+ var justFilename = Path . GetFileName ( configFile ) ;
31+ logFile = Path . Combine ( config . logDir , justFilename . Substring ( 0 , justFilename . Length - config . configExt . Length ) + ".log" ) ;
3332
3433 // FIXME: if (!init_security_attributes_allow_all (&sa))
3534 //{
3635 // MSG (M_SYSERR, "InitializeSecurityDescriptor start_" PACKAGE " failed");
3736 // goto finish;
3837 //}
39-
40- logFile = new StreamWriter ( File . Open ( logFilename ,
41- config . logAppend ? FileMode . Append : FileMode . Create ,
42- FileAccess . Write ,
43- FileShare . Read ) , new UTF8Encoding ( false ) ) ;
44- logFile . AutoFlush = true ;
45-
46- /// SET UP PROCESS START INFO
47- string [ ] procArgs = {
48- "--config" ,
49- "\" " + configFile + "\" " ,
50- "--service " ,
51- "\" " + exitEvent + "\" " + " 0"
52- } ;
53- this . startInfo = new System . Diagnostics . ProcessStartInfo ( )
54- {
55- RedirectStandardInput = true ,
56- RedirectStandardOutput = true ,
57- RedirectStandardError = true ,
58- WindowStyle = System . Diagnostics . ProcessWindowStyle . Hidden ,
59-
60- FileName = config . exePath ,
61- Arguments = String . Join ( " " , procArgs ) ,
62- WorkingDirectory = config . configDir ,
63-
64- UseShellExecute = false ,
65- /* create_new_console is not exposed -- but we probably don't need it?*/
66- } ;
6738 }
6839
6940 // set exit event so that openvpn will terminate
@@ -75,7 +46,7 @@ public void SignalProcess()
7546 }
7647 try
7748 {
78- if ( ! process . HasExited )
49+ if ( process != null && ! process . HasExited )
7950 {
8051
8152 try
@@ -117,7 +88,7 @@ public void StopProcess(int timeout)
11788 }
11889 try
11990 {
120- if ( ! process . WaitForExit ( timeout ) )
91+ if ( process != null && ! process . WaitForExit ( timeout ) )
12192 {
12293 process . Exited -= Watchdog ; // Don't restart the process after kill
12394 process . Kill ( ) ;
@@ -128,8 +99,8 @@ public void StopProcess(int timeout)
12899
129100 public void Wait ( )
130101 {
131- process . WaitForExit ( ) ;
132- logFile . Close ( ) ;
102+ if ( process != null )
103+ process . WaitForExit ( ) ;
133104 }
134105
135106 public void Restart ( )
@@ -139,7 +110,7 @@ public void Restart()
139110 restartTimer . Stop ( ) ;
140111 }
141112 /* try-catch... because there could be a concurrency issue (write-after-read) here? */
142- if ( ! process . HasExited )
113+ if ( process != null && ! process . HasExited )
143114 {
144115 process . Exited -= Watchdog ;
145116 process . Exited += FastRestart ; // Restart the process after kill
@@ -158,12 +129,6 @@ public void Restart()
158129 }
159130 }
160131
161- private void WriteToLog ( object sendingProcess , DataReceivedEventArgs e )
162- {
163- if ( e != null )
164- logFile . WriteLine ( e . Data ) ;
165- }
166-
167132 /// Restart after 10 seconds
168133 /// For use with unexpected terminations
169134 private void Watchdog ( object sender , EventArgs e )
@@ -193,21 +158,53 @@ private void FastRestart(object sender, EventArgs e)
193158 restartTimer . Start ( ) ;
194159 }
195160
161+ private const string PipeName = @"openvpn\service" ;
162+
196163 public void Start ( )
197164 {
198- process = new System . Diagnostics . Process ( ) ;
165+ using ( var pipeClient = new NamedPipeClientStream ( "." , PipeName , PipeDirection . InOut , PipeOptions . Asynchronous ) )
166+ {
167+ config . LogMessage ( "Connecting to iservice pipe..." ) ;
168+ pipeClient . Connect ( 5000 ) ;
199169
200- process . StartInfo = startInfo ;
201- process . EnableRaisingEvents = true ;
170+ using ( var writer = new BinaryWriter ( pipeClient , Encoding . Unicode ) )
171+ using ( var reader = new StreamReader ( pipeClient , Encoding . Unicode ) )
172+ {
173+ // send startup info
174+ var logOption = config . logAppend ? "--log-append " : "--log" ;
175+ var cmdLine = $ "{ logOption } \" { logFile } \" --config \" { configFile } \" --service \" { exitEvent } \" 0 --pull-filter ignore route-method";
202176
203- process . OutputDataReceived += WriteToLog ;
204- process . ErrorDataReceived += WriteToLog ;
205- process . Exited += Watchdog ;
177+ // config_dir + \0 + options + \0 + password + \0
178+ var startupInfo = $ "{ config . configDir } \0 { cmdLine } \0 \0 ";
206179
207- process . Start ( ) ;
208- process . BeginErrorReadLine ( ) ;
209- process . BeginOutputReadLine ( ) ;
210- process . PriorityClass = config . priorityClass ;
180+ byte [ ] messageBytes = Encoding . Unicode . GetBytes ( startupInfo ) ;
181+ writer . Write ( messageBytes ) ;
182+ writer . Flush ( ) ;
183+
184+ config . LogMessage ( "Sent startupInfo to iservice" ) ;
185+
186+ // read openvpn process pid from the pipe
187+ string [ ] lines = { reader . ReadLine ( ) , reader . ReadLine ( ) } ;
188+
189+ config . LogMessage ( $ "Read from iservice: { string . Join ( " " , lines ) } ") ;
190+ var errorCode = Convert . ToInt32 ( lines [ 0 ] , 16 ) ;
191+
192+ if ( errorCode == 0 )
193+ {
194+ var pid = Convert . ToInt32 ( lines [ 1 ] , 16 ) ;
195+
196+ process = Process . GetProcessById ( pid ) ;
197+ process . PriorityClass = config . priorityClass ;
198+ process . EnableRaisingEvents = true ;
199+ process . Exited += Watchdog ;
200+
201+ config . LogMessage ( $ "Add watchdog for openvpn process, pid { pid } ") ;
202+ } else
203+ {
204+ config . LogMessage ( "Error getting openvpn process pid" , EventLogEntryType . Error ) ;
205+ }
206+ }
207+ }
211208 }
212209 }
213210}
0 commit comments