2 using System.Collections.Generic;
3 using System.Diagnostics;
6 using System.Net.Sockets;
7 using System.Runtime.Remoting.Messaging;
10 namespace Mono.Debugger.Soft
12 public class LaunchOptions {
13 public string AgentArgs {
17 public bool Valgrind {
21 public ProcessLauncher CustomProcessLauncher {
25 public TargetProcessLauncher CustomTargetProcessLauncher {
29 public delegate Process ProcessLauncher (ProcessStartInfo info);
30 public delegate ITargetProcess TargetProcessLauncher (ProcessStartInfo info);
33 public class VirtualMachineManager
35 private delegate VirtualMachine LaunchCallback (ITargetProcess p, ProcessStartInfo info, Socket socket);
36 private delegate VirtualMachine ListenCallback (Socket dbg_sock, Socket con_sock);
37 private delegate VirtualMachine ConnectCallback (Socket dbg_sock, Socket con_sock, IPEndPoint dbg_ep, IPEndPoint con_ep);
39 internal VirtualMachineManager () {
42 public static VirtualMachine LaunchInternal (Process p, ProcessStartInfo info, Socket socket)
44 return LaunchInternal (new ProcessWrapper (p), info, socket);
47 public static VirtualMachine LaunchInternal (ITargetProcess p, ProcessStartInfo info, Socket socket) {
48 Socket accepted = null;
50 accepted = socket.Accept ();
55 Connection conn = new TcpConnection (accepted);
57 VirtualMachine vm = new VirtualMachine (p, conn);
59 if (info.RedirectStandardOutput)
60 vm.StandardOutput = p.StandardOutput;
62 if (info.RedirectStandardError)
63 vm.StandardError = p.StandardError;
65 conn.EventHandler = new EventHandler (vm);
72 public static IAsyncResult BeginLaunch (ProcessStartInfo info, AsyncCallback callback)
74 return BeginLaunch (info, callback, null);
77 public static IAsyncResult BeginLaunch (ProcessStartInfo info, AsyncCallback callback, LaunchOptions options)
80 throw new ArgumentNullException ("info");
82 Socket socket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
83 socket.Bind (new IPEndPoint (IPAddress.Loopback, 0));
85 IPEndPoint ep = (IPEndPoint) socket.LocalEndPoint;
87 // We need to inject our arguments into the psi
88 info.Arguments = string.Format ("{0} --debug --debugger-agent=transport=dt_socket,address={1}:{2}{3} {4}",
89 options == null || !options.Valgrind ? "" : info.FileName,
92 options == null || options.AgentArgs == null ? "" : "," + options.AgentArgs,
95 if (options != null && options.Valgrind)
96 info.FileName = "valgrind";
97 info.UseShellExecute = false;
99 if (info.RedirectStandardError)
100 info.StandardErrorEncoding = Encoding.UTF8;
102 if (info.RedirectStandardOutput)
103 info.StandardOutputEncoding = Encoding.UTF8;
106 if (options != null && options.CustomProcessLauncher != null)
107 p = new ProcessWrapper (options.CustomProcessLauncher (info));
108 else if (options != null && options.CustomTargetProcessLauncher != null)
109 p = options.CustomTargetProcessLauncher (info);
111 p = new ProcessWrapper (Process.Start (info));
113 p.Exited += delegate (object sender, EventArgs eargs) {
117 LaunchCallback c = new LaunchCallback (LaunchInternal);
118 return c.BeginInvoke (p, info, socket, callback, socket);
121 public static VirtualMachine EndLaunch (IAsyncResult asyncResult) {
122 if (asyncResult == null)
123 throw new ArgumentNullException ("asyncResult");
125 if (!asyncResult.IsCompleted)
126 asyncResult.AsyncWaitHandle.WaitOne ();
128 AsyncResult result = (AsyncResult) asyncResult;
129 LaunchCallback cb = (LaunchCallback) result.AsyncDelegate;
130 return cb.EndInvoke (asyncResult);
133 public static VirtualMachine Launch (ProcessStartInfo info)
135 return Launch (info, null);
138 public static VirtualMachine Launch (ProcessStartInfo info, LaunchOptions options)
140 return EndLaunch (BeginLaunch (info, null, options));
143 public static VirtualMachine Launch (string[] args)
145 return Launch (args, null);
148 public static VirtualMachine Launch (string[] args, LaunchOptions options)
150 ProcessStartInfo pi = new ProcessStartInfo ("mono");
151 pi.Arguments = String.Join (" ", args);
153 return Launch (pi, options);
156 public static VirtualMachine ListenInternal (Socket dbg_sock, Socket con_sock) {
157 Socket con_acc = null;
158 Socket dbg_acc = null;
160 if (con_sock != null) {
162 con_acc = con_sock.Accept ();
163 } catch (Exception) {
172 dbg_acc = dbg_sock.Accept ();
173 } catch (Exception) {
174 if (con_sock != null) {
183 if (con_sock != null) {
184 if (con_sock.Connected)
185 con_sock.Disconnect (false);
189 if (dbg_sock.Connected)
190 dbg_sock.Disconnect (false);
193 Connection transport = new TcpConnection (dbg_acc);
194 StreamReader console = con_acc != null? new StreamReader (new NetworkStream (con_acc)) : null;
196 return Connect (transport, console, null);
199 public static IAsyncResult BeginListen (IPEndPoint dbg_ep, AsyncCallback callback) {
200 return BeginListen (dbg_ep, null, callback);
203 public static IAsyncResult BeginListen (IPEndPoint dbg_ep, IPEndPoint con_ep, AsyncCallback callback)
205 int dbg_port, con_port;
206 return BeginListen (dbg_ep, con_ep, callback, out dbg_port, out con_port);
209 public static IAsyncResult BeginListen (IPEndPoint dbg_ep, IPEndPoint con_ep, AsyncCallback callback,
210 out int dbg_port, out int con_port)
212 dbg_port = con_port = 0;
214 Socket dbg_sock = null;
215 Socket con_sock = null;
217 dbg_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
218 dbg_sock.Bind (dbg_ep);
219 dbg_sock.Listen (1000);
220 dbg_port = ((IPEndPoint) dbg_sock.LocalEndPoint).Port;
222 if (con_ep != null) {
223 con_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
224 con_sock.Bind (con_ep);
225 con_sock.Listen (1000);
226 con_port = ((IPEndPoint) con_sock.LocalEndPoint).Port;
229 ListenCallback c = new ListenCallback (ListenInternal);
230 return c.BeginInvoke (dbg_sock, con_sock, callback, con_sock ?? dbg_sock);
233 public static VirtualMachine EndListen (IAsyncResult asyncResult) {
234 if (asyncResult == null)
235 throw new ArgumentNullException ("asyncResult");
237 if (!asyncResult.IsCompleted)
238 asyncResult.AsyncWaitHandle.WaitOne ();
240 AsyncResult result = (AsyncResult) asyncResult;
241 ListenCallback cb = (ListenCallback) result.AsyncDelegate;
242 return cb.EndInvoke (asyncResult);
245 public static VirtualMachine Listen (IPEndPoint dbg_ep)
247 return Listen (dbg_ep, null);
250 public static VirtualMachine Listen (IPEndPoint dbg_ep, IPEndPoint con_ep)
252 return EndListen (BeginListen (dbg_ep, con_ep, null));
256 * Connect to a virtual machine listening at the specified address.
258 public static VirtualMachine Connect (IPEndPoint endpoint) {
259 return Connect (endpoint, null);
262 public static VirtualMachine Connect (IPEndPoint endpoint, IPEndPoint consoleEndpoint) {
263 if (endpoint == null)
264 throw new ArgumentNullException ("endpoint");
266 return EndConnect (BeginConnect (endpoint, consoleEndpoint, null));
269 public static VirtualMachine ConnectInternal (Socket dbg_sock, Socket con_sock, IPEndPoint dbg_ep, IPEndPoint con_ep) {
270 if (con_sock != null) {
272 con_sock.Connect (con_ep);
273 } catch (Exception) {
282 dbg_sock.Connect (dbg_ep);
283 } catch (Exception) {
284 if (con_sock != null) {
292 Connection transport = new TcpConnection (dbg_sock);
293 StreamReader console = con_sock != null? new StreamReader (new NetworkStream (con_sock)) : null;
295 return Connect (transport, console, null);
298 public static IAsyncResult BeginConnect (IPEndPoint dbg_ep, AsyncCallback callback) {
299 return BeginConnect (dbg_ep, null, callback);
302 public static IAsyncResult BeginConnect (IPEndPoint dbg_ep, IPEndPoint con_ep, AsyncCallback callback) {
303 Socket dbg_sock = null;
304 Socket con_sock = null;
306 dbg_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
308 if (con_ep != null) {
309 con_sock = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
312 ConnectCallback c = new ConnectCallback (ConnectInternal);
313 return c.BeginInvoke (dbg_sock, con_sock, dbg_ep, con_ep, callback, con_sock ?? dbg_sock);
316 public static VirtualMachine EndConnect (IAsyncResult asyncResult) {
317 if (asyncResult == null)
318 throw new ArgumentNullException ("asyncResult");
320 if (!asyncResult.IsCompleted)
321 asyncResult.AsyncWaitHandle.WaitOne ();
323 AsyncResult result = (AsyncResult) asyncResult;
324 ConnectCallback cb = (ConnectCallback) result.AsyncDelegate;
325 return cb.EndInvoke (asyncResult);
328 public static void CancelConnection (IAsyncResult asyncResult)
330 ((Socket)asyncResult.AsyncState).Close ();
333 public static VirtualMachine Connect (Connection transport, StreamReader standardOutput, StreamReader standardError)
335 VirtualMachine vm = new VirtualMachine (null, transport);
337 vm.StandardOutput = standardOutput;
338 vm.StandardError = standardError;
340 transport.EventHandler = new EventHandler (vm);