[Monodevelop-patches-list] r2489 - in trunk/MonoDevelop/Extras/BooBinding: . BooShell BooShellServer Gui Gui/OptionPanels Properties Remoting
Peter Johanson <latexer@gentoo.org>
pjohanson at mono-cvs.ximian.com
Wed Apr 27 22:38:46 EDT 2005
Author: pjohanson
Date: 2005-04-27 22:38:46 -0400 (Wed, 27 Apr 2005)
New Revision: 2489
Added:
trunk/MonoDevelop/Extras/BooBinding/BooShell/
trunk/MonoDevelop/Extras/BooBinding/BooShell/BooShell.boo
trunk/MonoDevelop/Extras/BooBinding/BooShellServer/
trunk/MonoDevelop/Extras/BooBinding/BooShellServer/BooShellServer.boo
trunk/MonoDevelop/Extras/BooBinding/Remoting/
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixChannel.cs
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClient.cs
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientChannel.cs
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientTransportSink.cs
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientTransportSinkProvider.cs
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixListener.cs
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixMessageIO.cs
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixServerChannel.cs
trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixServerTransportSink.cs
Modified:
trunk/MonoDevelop/Extras/BooBinding/BooShellPadContent.boo
trunk/MonoDevelop/Extras/BooBinding/ChangeLog
trunk/MonoDevelop/Extras/BooBinding/Gui/BooShellModel.boo
trunk/MonoDevelop/Extras/BooBinding/Gui/IShellModel.boo
trunk/MonoDevelop/Extras/BooBinding/Gui/OptionPanels/CodeCompilationPanel.boo
trunk/MonoDevelop/Extras/BooBinding/Gui/OptionPanels/GeneralShellPanel.boo
trunk/MonoDevelop/Extras/BooBinding/Gui/ShellTextView.boo
trunk/MonoDevelop/Extras/BooBinding/Makefile.am
trunk/MonoDevelop/Extras/BooBinding/Properties/ShellProperties.boo
Log:
Lots of updates to the boo shell, interpreter now runs out of process, and added the option of loading the assemblies from the currently open combine/project.
Added: trunk/MonoDevelop/Extras/BooBinding/BooShell/BooShell.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/BooShell/BooShell.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/BooShell/BooShell.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,127 @@
+#region license
+// Copyright (c) 2005, Peter Johanson (latexer at gentoo.org)
+// All rights reserved.
+//
+// BooBinding is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// BooBinding is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with BooBinding; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#endregion
+
+namespace BooBinding.BooShell
+
+import System
+import System.Collections
+import System.IO
+import Boo.Lang.Interpreter
+import Boo.Lang.Compiler
+
+import Gtk
+import GLib
+
+class BooShell(MarshalByRefObject):
+ private _interpreter = InteractiveInterpreter(RememberLastValue: true, Print: print)
+
+ private _commandQueue = Queue()
+ private _outputQueue = Queue()
+
+ private _thread as System.Threading.Thread
+
+ private _processing as string = "true"
+
+ def Reset() as bool:
+ EnqueueCommand (ShellCommand (ShellCommandType.Reset, null))
+ return true
+
+ def LoadAssembly (assemblyPath as string) as bool:
+ EnqueueCommand (ShellCommand (ShellCommandType.Load, assemblyPath))
+ return true
+
+ def GetOutput() as (string):
+ _tmp as string
+ lock _processing:
+ _tmp = _processing
+
+ while _tmp == "true":
+ lock _processing:
+ _tmp = _processing
+ // Sleep to let other thread process (and grab lock)
+ System.Threading.Thread.Sleep (10)
+
+ ret as (string)
+ lock _outputQueue:
+ if _outputQueue.Count > 0:
+ ret = array (string, _outputQueue.Count)
+ _outputQueue.CopyTo (ret, 0)
+ _outputQueue.Clear()
+
+ return ret
+
+ def QueueInput (line as string):
+ EnqueueCommand (ShellCommand (ShellCommandType.Eval, line))
+
+ def ThreadRun():
+ Application.Init()
+ GLib.Idle.Add(ProcessCommands)
+ Application.Run()
+
+ def ProcessCommands() as bool:
+ com as ShellCommand
+ lock _commandQueue:
+ if _commandQueue.Count > 0:
+ com = _commandQueue.Dequeue()
+ if com.Type == ShellCommandType.Eval:
+ if com.Data is not null:
+ lock _outputQueue:
+ _interpreter.LoopEval(com.Data)
+ elif com.Type == ShellCommandType.Reset:
+ _interpreter.Reset()
+ elif com.Type == ShellCommandType.Load:
+ if com.Data is not null:
+ _interpreter.load(com.Data)
+
+ com.Type = ShellCommandType.NoOp
+
+ lock _commandQueue:
+ if _commandQueue.Count == 0:
+ lock _processing:
+ _processing = "false"
+
+ return true
+
+ def Run():
+ _thread = System.Threading.Thread(ThreadRun)
+ _thread.Start()
+
+ def print(obj):
+ _outputQueue.Enqueue(obj)
+
+ def EnqueueCommand (command as ShellCommand):
+ lock _commandQueue:
+ _commandQueue.Enqueue (command)
+ lock _processing:
+ _processing = "true"
+
+
+public enum ShellCommandType:
+ NoOp
+ Reset
+ Load
+ Eval
+
+public struct ShellCommand:
+ Type as ShellCommandType
+ Data as string
+
+ def constructor (type, data):
+ self.Type = type
+ self.Data = data
Modified: trunk/MonoDevelop/Extras/BooBinding/BooShellPadContent.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/BooShellPadContent.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/BooShellPadContent.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -43,7 +43,9 @@
def CreateBooShell():
_scroller = Gtk.ScrolledWindow()
- _shellView = ShellTextView (BooShellModel())
+ _user = System.Environment.GetEnvironmentVariable("USER")
+ _model = BooShellModel ("../AddIns/BackendBindings/BooShellServer.exe", "/tmp/md-booshell-${_user}")
+ _shellView = ShellTextView (_model)
_scroller.Add(_shellView)
override def RedrawContent():
@@ -52,4 +54,5 @@
override def Dispose():
_shellView.Dispose()
+ _scroller.Dispose()
Added: trunk/MonoDevelop/Extras/BooBinding/BooShellServer/BooShellServer.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/BooShellServer/BooShellServer.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/BooShellServer/BooShellServer.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,47 @@
+#region license
+// Copyright (c) 2005, Peter Johanson (latexer at gentoo.org)
+// All rights reserved.
+//
+// BooBinding is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// BooBinding is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with BooBinding; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#endregion
+
+namespace BooBinding.BooShellServer
+
+import System
+import System.IO
+import System.Collections
+
+import System.Net.Sockets
+import System.Runtime.Remoting
+import System.Runtime.Remoting.Channels
+
+import BooBinding.Remoting
+import BooBinding.BooShell
+import Mono.Posix
+
+if argv.Length != 1:
+ print "ERROR: BooShellServer called with an invalid number of arguments"
+ System.Environment.Exit(1)
+
+print "Starting server listening on ${argv[0]}"
+File.Delete (argv[0])
+props = Hashtable()
+props["path"] = argv[0]
+chan = UnixChannel (props, BinaryClientFormatterSinkProvider (), BinaryServerFormatterSinkProvider ())
+ChannelServices.RegisterChannel(chan);
+RemotingConfiguration.RegisterWellKnownServiceType(
+ typeof(BooShell), "BooShell", WellKnownObjectMode.Singleton);
+
+Console.ReadLine()
Modified: trunk/MonoDevelop/Extras/BooBinding/ChangeLog
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/ChangeLog 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/ChangeLog 2005-04-28 02:38:46 UTC (rev 2489)
@@ -1,4 +1,18 @@
2005-04-25 Peter Johanson <latexer at gentoo.org>
+ * Properties/GeneralShellProperties.boo:
+ * Gui/*: Lots of changes to handle new shell
+ handling, as well as adding the ability to
+ load the assemblies generated by the currently
+ open solution/combine.
+ * Remoting/*: Library for doing remoting
+ using unix sockets
+ * BooShell/BooShell.boo: New shell object
+ created out of process from MD for projection
+ * BooShellServer/BooShellServer.boo: Remoting
+ server for serving up the BooShell objects
+
+2005-04-25 Peter Johanson <latexer at gentoo.org>
+
* Initial import of the Boo addin.
Modified: trunk/MonoDevelop/Extras/BooBinding/Gui/BooShellModel.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Gui/BooShellModel.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Gui/BooShellModel.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -20,70 +20,115 @@
namespace BooBinding.Gui
import System
+import System.Diagnostics
import System.Collections
import System.IO
-import Boo.Lang.Interpreter
-import Boo.Lang.Compiler
import BooBinding.Properties
+import BooBinding.BooShell
+import BooBinding.Remoting
+import System.Runtime.Remoting
+import System.Runtime.Remoting.Channels
+
class BooShellModel(IShellModel):
+ private _props = BooShellProperties()
+
+ private _commandQueue = Queue()
+ private _outputQueue = Queue()
+
+ private _outputHandler as callable
- private _interpreter = InteractiveInterpreter(RememberLastValue: true, Print: print)
+ private _thread as System.Threading.Thread
- private _outSink as StreamWriter
- private _outSource as StreamReader
+ private _process as Process
- private props = BooShellProperties()
+ private _booShell as BooShell
MimeType as string:
get:
return "text/x-boo"
- def constructor():
- _stream = MemoryStream()
- _outSink = StreamWriter(_stream)
- _outSource = StreamReader (_stream)
-
Properties as ShellProperties:
get:
- return props
+ return _props
- def Reset() as bool:
- _interpreter.Reset()
- return true
-
- def ProcessInput (line as String) as (string):
- // Make sure our fake stdout is at the beginning
- _outSink.BaseStream.SetLength(0)
- _outSink.BaseStream.Seek(0, SeekOrigin.Begin)
+ def constructor ():
+ pass
- // Save tradition stdout, and redirect Console
- // to local StreamWriter. Catches any print, etc calls
- // to be output to the local shell
- _stdout = Console.Out
- Console.SetOut(_outSink)
+ def constructor (program_path as string, socket_path as string):
+ StartShellServer (program_path, socket_path)
+ GetRemoteShellObject (socket_path)
+ _booShell.Run()
- _interpreter.LoopEval(line)
+ def StartShellServer(program_path as string, socket_path as string):
+ psi = ProcessStartInfo()
+ psi.FileName = "mono"
+ psi.Arguments = "${program_path} ${socket_path}"
+ _process = Process.Start(psi)
+
+ def GetRemoteShellObject (socket_path as string):
+ chan = UnixChannel (Hashtable(), BinaryClientFormatterSinkProvider (), BinaryServerFormatterSinkProvider ())
+ ChannelServices.RegisterChannel(chan)
+ _booShell = Activator.GetObject (typeof(BooShell), "unix://${socket_path}?BooShell")
- // Restore stdout, and prep our fake stdout for reading
- Console.SetOut(_stdout)
- _outSink.Flush()
- _outSink.BaseStream.Seek(0, SeekOrigin.Begin)
+
+ def Reset() as bool:
+ _booShell.Reset()
+ return true
+
+ def LoadAssembly (assemblyPath as string) as bool:
+ _booShell.LoadAssembly (assemblyPath)
+ return true
+
+ def GetOutput() as (string):
+ ret as (string)
+ lock _outputQueue:
+ if _outputQueue.Count > 0:
+ ret = array (string, _outputQueue.Count)
+ _outputQueue.CopyTo (ret, 0)
+ _outputQueue.Clear()
- retList = ArrayList()
- _outputLine as string = _outSource.ReadLine()
+ return ret
- while _outputLine is not null:
- retList.Add(_outputLine)
- _outputLine = _outSource.ReadLine()
+
+ def QueueInput (line as string):
+ lock _commandQueue:
+ _commandQueue.Enqueue (line)
- ret = cast ((string), retList.ToArray(typeof(string)))
+ def ThreadRun():
+ while true:
+ com as string
+ lock _commandQueue:
+ if _commandQueue.Count > 0:
+ com = _commandQueue.Dequeue()
+ if com is not null:
+ _booShell.QueueInput (com)
+ lines = _booShell.GetOutput()
+ if lines is not null:
+ EnqueueOutput(lines)
+ com = null
+ lock _outputQueue:
+ if _outputHandler is not null:
+ _outputHandler()
- _ = _interpreter.LastValue
- if _ is not null:
- _interpreter.SetValue("_", _)
-
- return ret
+ def Run():
+ _thread = System.Threading.Thread(ThreadRun)
+ _thread.Start()
+
+ def RegisterOutputHandler (handler as callable):
+ _outputHandler = handler
+
+ def EnqueueOutput (lines as (string)):
+ lock _outputQueue:
+ for line in lines:
+ _outputQueue.Enqueue(line)
+
+ def Dispose():
+ _thread.Abort()
+ _process.Kill()
+ _booShell = null
+
def print(obj):
- print "${obj}"
+ lock _outputQueue:
+ _outputQueue.Enqueue(obj)
Modified: trunk/MonoDevelop/Extras/BooBinding/Gui/IShellModel.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Gui/IShellModel.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Gui/IShellModel.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -26,9 +26,23 @@
def Reset() as bool:
pass
- def ProcessInput (line as String) as (string):
+ def LoadAssembly (assemblyPath as string) as bool:
pass
+
+ def RegisterOutputHandler (handler as callable):
+ pass
+
+ def Run():
+ pass
+ def GetOutput() as (string):
+ pass
+
+ def QueueInput (line as string):
+ pass
+
+ def Dispose():
+ pass
Properties as ShellProperties:
get:
Modified: trunk/MonoDevelop/Extras/BooBinding/Gui/OptionPanels/CodeCompilationPanel.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Gui/OptionPanels/CodeCompilationPanel.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Gui/OptionPanels/CodeCompilationPanel.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -53,7 +53,7 @@
private outputAssembly = Entry ()
private outputDirectory = Entry()
- // Waiting on resolution of a boo bug before we can use this
+ // Waiting on easy method for setting entry text before using
//private outputDirectory as FolderEntry = FolderEntry ("Output Directory")
private compilerPath = Entry ()
private culture = Entry ()
Modified: trunk/MonoDevelop/Extras/BooBinding/Gui/OptionPanels/GeneralShellPanel.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Gui/OptionPanels/GeneralShellPanel.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Gui/OptionPanels/GeneralShellPanel.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -39,6 +39,7 @@
private autoIndentCheckButton = Gtk.CheckButton ()
private resetClearsScrollbackCheckButton = Gtk.CheckButton ()
private resetClearsHistoryCheckButton = Gtk.CheckButton ()
+ private loadAssemblyCheckButton = Gtk.CheckButton ()
private fontOptionsLabel = Gtk.Label ()
private fontButton = FontButton ()
@@ -55,6 +56,7 @@
autoIndentCheckButton.Label = GettextCatalog.GetString ("Automatically indent new lines in code blocks")
resetClearsScrollbackCheckButton.Label = GettextCatalog.GetString ("Shell reset clears scollback")
resetClearsHistoryCheckButton.Label = GettextCatalog.GetString ("Shell reset clears command history")
+ loadAssemblyCheckButton.Label = GettextCatalog.GetString ("Load project assemblies after building them (Causes shell reset)")
fontOptionsLabel.Markup = String.Format ("<b>{0}</b>", GettextCatalog.GetString ("Font"))
defaultMonoRadio = RadioButton (GettextCatalog.GetString ("Use default monospace font"))
customFontRadio = RadioButton (defaultMonoRadio, GettextCatalog.GetString ("Use custom font:"))
@@ -80,6 +82,9 @@
hboxTmp.PackStart (resetClearsHistoryCheckButton, false, false, 6)
vbox.PackStart (hboxTmp, false, false, 0)
hboxTmp = HBox()
+ hboxTmp.PackStart (loadAssemblyCheckButton, false, false, 6)
+ vbox.PackStart (hboxTmp, false, false, 0)
+ hboxTmp = HBox()
hboxTmp.PackStart (fontOptionsLabel, false, false, 0)
vbox.PackStart (hboxTmp, false, false, 12)
hboxTmp = HBox()
@@ -103,6 +108,7 @@
autoIndentCheckButton.Active = Properties.AutoIndentBlocks
resetClearsScrollbackCheckButton.Active = Properties.ResetClearsScrollback
resetClearsHistoryCheckButton.Active = Properties.ResetClearsHistory
+ loadAssemblyCheckButton.Active = Properties.LoadAssemblyAfterBuild
public override def StorePanelContents() as bool:
@@ -118,6 +124,8 @@
Properties.ResetClearsScrollback = resetClearsScrollbackCheckButton.Active
if Properties.ResetClearsHistory != resetClearsHistoryCheckButton.Active:
Properties.ResetClearsHistory = resetClearsHistoryCheckButton.Active
+ if Properties.LoadAssemblyAfterBuild != loadAssemblyCheckButton.Active:
+ Properties.LoadAssemblyAfterBuild = loadAssemblyCheckButton.Active
return true
private def ItemToggled (o, args as EventArgs):
Modified: trunk/MonoDevelop/Extras/BooBinding/Gui/ShellTextView.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Gui/ShellTextView.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Gui/ShellTextView.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -25,6 +25,7 @@
import Gtk
import Gdk
+import GLib
import Pango
import GtkSourceView
@@ -32,6 +33,7 @@
import MonoDevelop.Core.Services
import MonoDevelop.Services
import MonoDevelop.Core.Properties
+import MonoDevelop.Internal.Project
import Boo.IO
@@ -60,6 +62,12 @@
private _reset_clears_history as bool
private _reset_clears_scrollback as bool
private _auto_indent as bool
+ private _load_assembly_after_build as bool
+
+ private _projService as ProjectService
+ private _proj as Project
+
+ private _assembliesLoaded as bool
def constructor(model as IShellModel):
service = cast(SourceViewService,ServiceManager.GetService(typeof(SourceViewService)))
@@ -75,10 +83,12 @@
self.ModifyFont(Model.Properties.Font)
Model.Properties.InternalProperties.PropertyChanged += OnPropertyChanged
+ Model.RegisterOutputHandler (HandleOutput)
_auto_indent = Model.Properties.AutoIndentBlocks
_reset_clears_scrollback = Model.Properties.ResetClearsScrollback
_reset_clears_history = Model.Properties.ResetClearsHistory
+ _load_assembly_after_build = Model.Properties.LoadAssemblyAfterBuild
// The 'Freezer' tag is used to keep everything except
@@ -87,7 +97,69 @@
tag.Editable = false
Buffer.TagTable.Add (tag)
prompt(false)
+
+ _projService = ServiceManager.GetService(typeof(ProjectService))
+ _projService.EndBuild += ProjectCompiled
+ _projService.CurrentProjectChanged += ProjectChanged
+
+ // Run our model. Needs to happen for models which may spawn threads,
+ // processes, etc
+ Model.Run()
+ def ProjectChanged (sender, e as ProjectEventArgs):
+ _proj = e.Project
+
+ def ProjectCompiled (compiled as bool):
+ if _load_assembly_after_build and compiled:
+ Model.Reset()
+ resetGui()
+ loadProjectAssemblies ()
+
+ def loadProjectAssemblies():
+ for assembly in getProjectAssemblies ():
+ if (System.IO.File.Exists(assembly)):
+ Model.Reset()
+ Model.LoadAssembly (assembly)
+ _assembliesLoaded = true
+
+
+ def getProjectAssemblies():
+ _assemblies = []
+ if (_proj is not null):
+ assembly = _proj.GetOutputFileName()
+ if assembly is not null:
+ _assemblies.Add(assembly)
+ else:
+ _combine = _projService.CurrentOpenCombine
+ if _combine is null:
+ return
+
+ projects = _combine.GetAllProjects()
+ if projects is null:
+ return
+ for entry as Project in projects:
+ if entry is null:
+ continue
+ assembly = entry.GetOutputFileName()
+ if assembly is not null:
+ _assemblies.Add(assembly)
+
+ return _assemblies
+
+ def HandleOutput():
+ GLib.Idle.Add (outputIdleProcessor)
+
+ def outputIdleProcessor() as bool:
+ output = Model.GetOutput()
+ if output is not null:
+ for line as string in output:
+ processOutput (line )
+ prompt (true)
+ return false
+
+ override def Dispose():
+ Model.Dispose()
+
#region Overrides of the standard methods for event handling
override def OnPopulatePopup (menu as Gtk.Menu):
_copyScriptInput = ImageMenuItem (GettextCatalog.GetString ("Copy Script"))
@@ -98,26 +170,41 @@
_saveScriptToFile.Image = Gtk.Image (Stock.SaveAs, Gtk.IconSize.Menu)
_saveScriptToFile.Activated += OnSaveScript
+ _loadAssemblies = ImageMenuItem (GettextCatalog.GetString ("Load Project Assemblies (forces shell reset)"))
+ _loadAssemblies.Image = Gtk.Image (Stock.Add, Gtk.IconSize.Menu)
+ _loadAssemblies.Activated += def():
+ if Model.Reset ():
+ resetGui ()
+ loadProjectAssemblies ()
+
_reset = ImageMenuItem (GettextCatalog.GetString ("Reset Shell"))
_reset.Image = Gtk.Image (Stock.Clear, Gtk.IconSize.Menu)
_reset.Activated += def():
if Model.Reset():
resetGui()
-
+ _assembliesLoaded = false
+
if _scriptLines.Length <= 0:
_copyScriptInput.Sensitive = false
_saveScriptToFile.Sensitive = false
_reset.Sensitive = false
+ if (_assembliesLoaded == false) and (len (getProjectAssemblies ()) > 0):
+ _loadAssemblies.Sensitive = true
+ else:
+ _loadAssemblies.Sensitive = false
+
_sep = Gtk.SeparatorMenuItem()
menu.Prepend(_sep)
menu.Prepend(_copyScriptInput)
menu.Prepend(_saveScriptToFile)
+ menu.Prepend(_loadAssemblies)
menu.Prepend(_reset)
_sep.Show()
_copyScriptInput.Show()
_saveScriptToFile.Show()
+ _loadAssemblies.Show()
_reset.Show()
override def OnKeyPressEvent (ev as Gdk.EventKey):
@@ -250,13 +337,7 @@
#region local private methods
private def processInput (line as string):
- // Send our input out to be processed by the model
- // and handle any output received in return
- _results = self.Model.ProcessInput (line)
- if _results:
- for line as string in _results:
- processOutput (line)
- prompt(true)
+ Model.QueueInput (line)
private def processOutput (line as string):
end = Buffer.EndIter
@@ -309,6 +390,8 @@
_reset_clears_scrollback = Model.Properties.ResetClearsScrollback
elif e.Key == "ResetClearsHistory":
_reset_clears_history = Model.Properties.ResetClearsHistory
+ elif e.Key == "LoadAssemblyAfterBuild":
+ _load_assembly_after_build = Model.Properties.LoadAssemblyAfterBuild
return
Modified: trunk/MonoDevelop/Extras/BooBinding/Makefile.am
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Makefile.am 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Makefile.am 2005-04-28 02:38:46 UTC (rev 2489)
@@ -1,19 +1,36 @@
ADDIN_BUILD = $(top_builddir)/build/AddIns/BackendBindings
ASSEMBLY = $(ADDIN_BUILD)/BooBinding.dll
+REMOTING_LIB = $(ADDIN_BUILD)/BooShellUnixRemoting.dll
+BOOSHELL_LIB = $(ADDIN_BUILD)/BooShell.dll
+BOOSHELL_SERVER_EXE = $(ADDIN_BUILD)/BooShellServer.exe
DLLS = -r:System.Drawing \
-r:System.Xml \
+ -r:System.Runtime.Remoting \
-r:$(top_builddir)/build/bin/MonoDevelop.Core.dll \
-r:$(top_builddir)/build/bin/MonoDevelop.SourceEditor.dll \
-r:$(top_builddir)/build/bin/MonoDevelop.Base.dll \
-r:$(top_builddir)/build/bin/ICSharpCode.SharpRefactory.dll \
-r:$(top_builddir)/build/bin/MonoDevelop.Gui.Widgets.dll \
+ -r:$(BOOSHELL_LIB) \
+ -r:$(REMOTING_LIB) \
$(BOO_LIBS) \
$(GTK_SHARP_LIBS) \
$(GCONF_SHARP_LIBS) \
$(GTKSOURCEVIEW_SHARP_LIBS)
+REMOTING_DLLS = -r:System.Runtime.Remoting \
+ -r:Mono.Posix
+
+BOOSHELL_DLLS = $(GTK_SHARP_LIBS) \
+ $(BOO_LIBS)
+
+BOOSHELL_SERVER_DLLS = -r:$(BOOSHELL_LIB) \
+ -r:$(REMOTING_LIB) \
+ -r:System.Runtime.Remoting \
+ -r:Mono.Posix
+
FILES = \
Gui/ShellTextView.boo \
Gui/IShellModel.boo \
@@ -39,6 +56,20 @@
Parser/Tree.boo \
Parser/Visitor.boo
+REMOTING_FILES = Remoting/UnixChannel.cs \
+Remoting/UnixClient.cs \
+Remoting/UnixClientChannel.cs \
+Remoting/UnixClientTransportSink.cs \
+Remoting/UnixClientTransportSinkProvider.cs \
+Remoting/UnixListener.cs \
+Remoting/UnixMessageIO.cs \
+Remoting/UnixServerChannel.cs \
+Remoting/UnixServerTransportSink.cs
+
+BOOSHELL_FILES = BooShell/BooShell.boo
+
+BOOSHELL_SERVER_FILES= BooShellServer/BooShellServer.boo
+
TEMPLATES = \
templates/BooGtkSharpProject.xpt.xml \
templates/BooGtkSharpWindow.xft.xml \
@@ -46,10 +77,12 @@
templates/EmptyBooProject.xpt.xml
build_sources = $(addprefix $(srcdir)/, $(FILES))
+remoting_build_sources = $(addprefix $(srcdir)/, $(REMOTING_FILES))
+booshell_build_sources = $(addprefix $(srcdir)/, $(BOOSHELL_FILES))
+booshell_server_build_sources = $(addprefix $(srcdir)/, $(BOOSHELL_SERVER_FILES))
ADDIN = BooBinding.addin.xml
-
TEMPLATES_DIR = $(ADDIN_BUILD)/templates
build_TEMPLATES = $(addprefix $(TEMPLATES_DIR)/, $(notdir $(TEMPLATES)))
@@ -57,7 +90,8 @@
src_TEMPLATES = $(addprefix $(srcdir)/, $(TEMPLATES))
if ENABLE_BOO
-all: $(ASSEMBLY) $(ADDIN_BUILD)/$(ADDIN) $(build_TEMPLATES)
+all: $(ASSEMBLY) $(ADDIN_BUILD)/$(ADDIN) $(build_TEMPLATES) \
+ $(BOOSHELL_LIB) $(BOOSHELL_SERVER_EXE)
else
all:
endif
@@ -74,18 +108,32 @@
mkdir -p $(ADDIN_BUILD)
cp $(srcdir)/$(ADDIN) $(ADDIN_BUILD)/.
-$(ASSEMBLY): $(FILES)
+$(ASSEMBLY): $(FILES) $(REMOTING_LIB)
mkdir -p $(ADDIN_BUILD)
$(BOOC) $(DLLS) $(build_sources) -o:$@ -t:library
+$(REMOTING_LIB): $(REMOTING_FILES)
+ mkdir -p $(ADDIN_BUILD)
+ $(MCS) $(REMOTING_DLLS) $(remoting_build_sources) -out:$@ -t:library
+
+$(BOOSHELL_LIB): $(BOOSHELL_FILES)
+ mkdir -p $(ADDIN_BUILD)
+ $(BOOC) $(BOOSHELL_DLLS) $(booshell_build_sources) -o:$@ -t:library
+
+$(BOOSHELL_SERVER_EXE): $(BOOSHELL_SERVER_FILES)
+ mkdir -p $(ADDIN_BUILD)
+ $(BOOC) $(BOOSHELL_SERVER_DLLS) $(booshell_server_build_sources) -o:$@
+
if ENABLE_BOO
assemblydir = $(libdir)/monodevelop/AddIns/BackendBindings
-assembly_DATA = $(ASSEMBLY) $(ADDIN)
+assembly_DATA = $(ASSEMBLY) $(ADDIN) $(REMOTING_LIB) $(BOOSHELL_LIB) \
+ $(BOOSHELL_SERVER_EXE)
templatedir = $(assemblydir)/templates
template_DATA = $(TEMPLATES)
endif
-CLEANFILES = $(ASSEMBLY) $(ASSEMBLY).mdb
-EXTRA_DIST = $(FILES) $(ADDIN) $(TEMPLATES)
+CLEANFILES = $(ASSEMBLY) $(REMOTING_LIB) $(BOOSHELL_LIB) $(BOOSHELL_SERVER_EXE)
+EXTRA_DIST = $(FILES) $(ADDIN) $(TEMPLATES) $(REMOTING_FILES) \
+ $(BOOSHELL_FILES) $(BOOSHELL_SERVER_FILES)
Modified: trunk/MonoDevelop/Extras/BooBinding/Properties/ShellProperties.boo
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Properties/ShellProperties.boo 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Properties/ShellProperties.boo 2005-04-28 02:38:46 UTC (rev 2489)
@@ -56,3 +56,9 @@
return properties.GetProperty ("ResetClearsHistory", true)
set:
properties.SetProperty ("ResetClearsHistory", value)
+
+ LoadAssemblyAfterBuild as bool:
+ get:
+ return properties.GetProperty ("LoadAssemblyAfterBuild", true)
+ set:
+ properties.SetProperty ("LoadAssemblyAfterBuild", value)
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixChannel.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixChannel.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixChannel.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,145 @@
+//
+// System.Runtime.Remoting.Channels.Unix.UnixChannel.cs
+//
+// Author: Rodrigo Moya (rodrigo at ximian.com)
+// Lluis Sanchez Gual (lluis at ideary.com)
+//
+// 2002 (C) Copyright, Ximian, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Channels;
+using System.Text.RegularExpressions;
+
+namespace BooBinding.Remoting
+{
+ public class UnixChannel : IChannelReceiver, IChannel, IChannelSender
+ {
+ private UnixClientChannel _clientChannel;
+ private UnixServerChannel _serverChannel = null;
+ private string _name = "unix";
+ private int _priority = 1;
+
+ public UnixChannel (): this ("")
+ {
+ }
+
+ public UnixChannel (string path)
+ {
+ Hashtable ht = new Hashtable();
+ ht["path"] = path;
+ Init(ht, null, null);
+ }
+
+ void Init (IDictionary properties, IClientChannelSinkProvider clientSink, IServerChannelSinkProvider serverSink)
+ {
+ _clientChannel = new UnixClientChannel (properties,clientSink);
+
+ if(properties["path"] != null)
+ _serverChannel = new UnixServerChannel(properties, serverSink);
+
+ object val = properties ["name"];
+ if (val != null) _name = val as string;
+
+ val = properties ["priority"];
+ if (val != null) _priority = Convert.ToInt32 (val);
+ }
+
+
+ public UnixChannel (IDictionary properties,
+ IClientChannelSinkProvider clientSinkProvider,
+ IServerChannelSinkProvider serverSinkProvider)
+ {
+ Init (properties, clientSinkProvider, serverSinkProvider);
+ }
+
+ public IMessageSink CreateMessageSink(string url, object remoteChannelData, out string objectURI)
+ {
+ return _clientChannel.CreateMessageSink(url, remoteChannelData, out objectURI);
+ }
+
+ public string ChannelName
+ {
+ get { return _name; }
+ }
+
+ public int ChannelPriority
+ {
+ get { return _priority; }
+ }
+
+ public void StartListening (object data)
+ {
+ if (_serverChannel != null) _serverChannel.StartListening (data);
+ }
+
+ public void StopListening (object data)
+ {
+ if (_serverChannel != null) _serverChannel.StopListening(data);
+ }
+
+ public string[] GetUrlsForUri (string uri)
+ {
+ if (_serverChannel != null) return _serverChannel.GetUrlsForUri(uri);
+ else return null;
+ }
+
+ public object ChannelData
+ {
+ get
+ {
+ if (_serverChannel != null) return _serverChannel.ChannelData;
+ else return null;
+ }
+ }
+
+ public string Parse (string url, out string objectURI)
+ {
+ return UnixChannel.ParseUnixURL (url, out objectURI);
+ }
+
+ internal static string ParseUnixURL (string url, out string objectURI)
+ {
+ // format: "unix:///path/to/unix/socket?/path/to/object"
+
+ objectURI = null;
+
+ Match m = Regex.Match (url, "unix://?([^?]*)[?]?(.*)$");
+
+ if (!m.Success)
+ return null;
+
+ string sockPath = m.Groups[1].Value;
+ objectURI = m.Groups[2].Value;
+
+
+ if (objectURI == string.Empty)
+ objectURI = null;
+
+ return sockPath;
+ }
+ }
+}
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClient.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClient.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClient.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,231 @@
+//
+// UnixListener.cs
+//
+// Authors:
+// Joe Shaw (joeshaw at novell.com)
+//
+// Copyright (C) 2004-2005 Novell, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Runtime.InteropServices;
+
+using Mono.Posix;
+
+namespace BooBinding.Remoting {
+
+ public class UnixClient : IDisposable {
+ NetworkStream stream;
+ Socket client;
+ bool disposed;
+
+ public UnixClient ()
+ {
+ if (client != null) {
+ client.Close ();
+ client = null;
+ }
+
+ client = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
+ }
+
+ public UnixClient (string path) : this ()
+ {
+ if (path == null)
+ throw new ArgumentNullException ("ep");
+
+ Connect (path);
+ }
+
+ public UnixClient (UnixEndPoint ep) : this ()
+ {
+ if (ep == null)
+ throw new ArgumentNullException ("ep");
+
+ Connect (ep);
+ }
+
+ // UnixListener uses this when accepting a connection.
+ internal UnixClient (Socket sock)
+ {
+ Client = sock;
+ }
+
+ protected Socket Client {
+ get { return client; }
+ set {
+ client = value;
+ stream = null;
+ }
+ }
+
+ public PeerCred PeerCredential {
+ get {
+ CheckDisposed ();
+ return new PeerCred (client);
+ }
+ }
+
+ public LingerOption LingerState {
+ get {
+ CheckDisposed ();
+ return (LingerOption) client.GetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.Linger);
+ }
+
+ set {
+ CheckDisposed ();
+ client.SetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.Linger, value);
+ }
+ }
+
+ public int ReceiveBufferSize {
+ get {
+ CheckDisposed ();
+ return (int) client.GetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.ReceiveBuffer);
+ }
+
+ set {
+ CheckDisposed ();
+ client.SetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.ReceiveBuffer, value);
+ }
+ }
+
+ public int ReceiveTimeout {
+ get {
+ CheckDisposed ();
+ return (int) client.GetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.ReceiveTimeout);
+ }
+
+ set {
+ CheckDisposed ();
+ client.SetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.ReceiveTimeout, value);
+ }
+ }
+
+ public int SendBufferSize {
+ get {
+ CheckDisposed ();
+ return (int) client.GetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.SendBuffer);
+ }
+
+ set {
+ CheckDisposed ();
+ client.SetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.SendBuffer, value);
+ }
+ }
+
+ public int SendTimeout {
+ get {
+ CheckDisposed ();
+ return (int) client.GetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.SendTimeout);
+ }
+
+ set {
+ CheckDisposed ();
+ client.SetSocketOption (SocketOptionLevel.Socket,
+ SocketOptionName.SendTimeout, value);
+ }
+ }
+
+ public void Close ()
+ {
+ CheckDisposed ();
+ Dispose ();
+ }
+
+ public void Connect (UnixEndPoint remoteEndPoint)
+ {
+ CheckDisposed ();
+ client.Connect (remoteEndPoint);
+ stream = new NetworkStream (client, true);
+ }
+
+ public void Connect (string path)
+ {
+ CheckDisposed ();
+ Connect (new UnixEndPoint (path));
+ }
+
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ if (disposed)
+ return;
+
+ if (disposing) {
+ // release managed resources
+ NetworkStream s = stream;
+ stream = null;
+ if (s != null) {
+ // This closes the socket as well, as the NetworkStream
+ // owns the socket.
+ s.Close();
+ s = null;
+ } else if (client != null){
+ client.Close ();
+ }
+ client = null;
+ }
+
+ disposed = true;
+ }
+
+ public NetworkStream GetStream ()
+ {
+ CheckDisposed ();
+ if (stream == null)
+ stream = new NetworkStream (client, true);
+
+ return stream;
+ }
+
+ void CheckDisposed ()
+ {
+ if (disposed)
+ throw new ObjectDisposedException (GetType().FullName);
+ }
+
+ ~UnixClient ()
+ {
+ Dispose (false);
+ }
+ }
+}
+
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientChannel.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientChannel.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientChannel.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,134 @@
+//
+// System.Runtime.Remoting.Channels.Unix.UnixClientChannel.cs
+//
+// Author: Dietmar Maurer (dietmar at ximian.com)
+// Lluis Sanchez Gual (lluis at ideary.com)
+//
+// 2002 (C) Copyright, Ximian, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.IO;
+using System.Net.Sockets;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Channels;
+using System.Threading;
+
+namespace BooBinding.Remoting
+{
+ public class UnixClientChannel : IChannelSender, IChannel
+ {
+ int priority = 1;
+ string name = "unix";
+ IClientChannelSinkProvider _sinkProvider;
+
+ public UnixClientChannel ()
+ {
+ _sinkProvider = new BinaryClientFormatterSinkProvider ();
+ _sinkProvider.Next = new UnixClientTransportSinkProvider ();
+ }
+
+ public UnixClientChannel (IDictionary properties, IClientChannelSinkProvider sinkProvider)
+ {
+ object val = properties ["name"];
+ if (val != null) name = val as string;
+
+ val = properties ["priority"];
+ if (val != null) priority = Convert.ToInt32 (val);
+
+ if (sinkProvider != null)
+ {
+ _sinkProvider = sinkProvider;
+
+ // add the unix provider at the end of the chain
+ IClientChannelSinkProvider prov = sinkProvider;
+ while (prov.Next != null) prov = prov.Next;
+ prov.Next = new UnixClientTransportSinkProvider ();
+
+ // Note: a default formatter is added only when
+ // no sink providers are specified in the config file.
+ }
+ else
+ {
+ _sinkProvider = new BinaryClientFormatterSinkProvider ();
+ _sinkProvider.Next = new UnixClientTransportSinkProvider ();
+ }
+
+ }
+
+ public UnixClientChannel (string name, IClientChannelSinkProvider sinkProvider)
+ {
+ this.name = name;
+ _sinkProvider = sinkProvider;
+
+ // add the unix provider at the end of the chain
+ IClientChannelSinkProvider prov = sinkProvider;
+ while (prov.Next != null) prov = prov.Next;
+ prov.Next = new UnixClientTransportSinkProvider ();
+ }
+
+ public string ChannelName
+ {
+ get {
+ return name;
+ }
+ }
+
+ public int ChannelPriority
+ {
+ get {
+ return priority;
+ }
+ }
+
+ public IMessageSink CreateMessageSink (string url,
+ object remoteChannelData,
+ out string objectURI)
+ {
+ if (url != null && Parse (url, out objectURI) != null)
+ return (IMessageSink) _sinkProvider.CreateSink (this, url, remoteChannelData);
+
+ if (remoteChannelData != null) {
+ IChannelDataStore ds = remoteChannelData as IChannelDataStore;
+ if (ds != null && ds.ChannelUris.Length > 0)
+ url = ds.ChannelUris [0];
+ else {
+ objectURI = null;
+ return null;
+ }
+ }
+
+ if (Parse (url, out objectURI) == null)
+ return null;
+
+ return (IMessageSink) _sinkProvider.CreateSink (this, url, remoteChannelData);
+ }
+
+ public string Parse (string url, out string objectURI)
+ {
+ return UnixChannel.ParseUnixURL (url, out objectURI);
+ }
+ }
+}
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientTransportSink.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientTransportSink.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientTransportSink.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,235 @@
+//
+// System.Runtime.Remoting.Channels.Unix.UnixClientTransportSink.cs
+//
+// Author: Dietmar Maurer (dietmar at ximian.com)
+// Lluis Sanchez Gual (lluis at ideary.com)
+//
+// 2002 (C) Copyright, Ximian, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Remoting.Channels;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Messaging;
+using System.Collections;
+using System.IO;
+using System.Threading;
+
+namespace BooBinding.Remoting
+{
+ internal class UnixClientTransportSink : IClientChannelSink
+ {
+ string _path;
+ string _url;
+
+ public UnixClientTransportSink (string url)
+ {
+ string objectUri;
+ _path = UnixChannel.ParseUnixURL (url, out objectUri);
+ _url = url;
+ }
+
+ public IDictionary Properties
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public IClientChannelSink NextChannelSink
+ {
+ get
+ {
+ // we are the last one
+ return null;
+ }
+ }
+
+ public void AsyncProcessRequest (IClientChannelSinkStack sinkStack, IMessage msg,
+ ITransportHeaders headers, Stream requestStream)
+ {
+ UnixConnection connection = null;
+ bool isOneWay = RemotingServices.IsOneWay (((IMethodMessage)msg).MethodBase);
+
+ try
+ {
+ if (headers == null) headers = new TransportHeaders();
+ headers [CommonTransportKeys.RequestUri] = ((IMethodMessage)msg).Uri;
+
+ // Sends the stream using a connection from the pool
+ // and creates a WorkItem that will wait for the
+ // response of the server
+
+ connection = new UnixConnection (new UnixClient (_path));
+ UnixMessageIO.SendMessageStream (connection.Stream, requestStream, headers, connection.Buffer);
+
+ if (!isOneWay)
+ {
+ sinkStack.Push (this, connection);
+ ThreadPool.QueueUserWorkItem (new WaitCallback(ReadAsyncUnixMessage), sinkStack);
+ }
+ else
+ connection.Close();
+ }
+ catch
+ {
+ if (connection != null) connection.Close();
+ if (!isOneWay) throw;
+ }
+ }
+
+ private void ReadAsyncUnixMessage(object data)
+ {
+ // This method is called by a new thread to asynchronously
+ // read the response to a request
+
+ // The stack was provided as state data in QueueUserWorkItem
+ IClientChannelSinkStack stack = (IClientChannelSinkStack)data;
+
+ // The first sink in the stack is this sink. Pop it and
+ // get the status data, which is the UnixConnection used to send
+ // the request
+ UnixConnection connection = (UnixConnection)stack.Pop(this);
+
+ try
+ {
+ ITransportHeaders responseHeaders;
+
+ // Read the response, blocking if necessary
+ MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream);
+
+ if (status != MessageStatus.MethodMessage)
+ throw new RemotingException ("Unknown response message from server");
+
+ Stream responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
+
+ // Free the connection, so it can be reused
+ connection.Close();
+ connection = null;
+
+ // Ok, proceed with the other sinks
+ stack.AsyncProcessResponse (responseHeaders, responseStream);
+ }
+ catch
+ {
+ if (connection != null) connection.Close();
+ throw;
+ }
+ }
+
+ public void AsyncProcessResponse (IClientResponseChannelSinkStack sinkStack,
+ object state, ITransportHeaders headers,
+ Stream stream)
+ {
+ // Should never be called
+ throw new NotSupportedException();
+ }
+
+ public Stream GetRequestStream (IMessage msg, ITransportHeaders headers)
+ {
+ return null;
+ }
+
+ public void ProcessMessage (IMessage msg,
+ ITransportHeaders requestHeaders,
+ Stream requestStream,
+ out ITransportHeaders responseHeaders,
+ out Stream responseStream)
+ {
+ UnixConnection connection = null;
+ try
+ {
+ if (requestHeaders == null) requestHeaders = new TransportHeaders();
+ requestHeaders [CommonTransportKeys.RequestUri] = ((IMethodMessage)msg).Uri;
+
+ // Sends the message
+ connection = new UnixConnection (new UnixClient (_path));
+
+ UnixMessageIO.SendMessageStream (connection.Stream, requestStream, requestHeaders, connection.Buffer);
+
+ // Reads the response
+ MessageStatus status = UnixMessageIO.ReceiveMessageStatus (connection.Stream);
+
+ if (status != MessageStatus.MethodMessage)
+ throw new RemotingException ("Unknown response message from server, status: " + status);
+
+ responseStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out responseHeaders, connection.Buffer);
+ }
+ finally
+ {
+ if (connection != null)
+ connection.Close();
+ }
+ }
+
+ }
+
+ internal class UnixConnection
+ {
+ DateTime _controlTime;
+ Stream _stream;
+ UnixClient _client;
+ byte[] _buffer;
+
+ public UnixConnection (UnixClient client)
+ {
+ _client = client;
+ _client.ReceiveTimeout = 10000; // 10 seconds
+ _stream = client.GetStream();
+ _controlTime = DateTime.Now;
+ _buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
+ }
+
+ public UnixClient Client {
+ get { return _client; }
+ }
+
+ public Stream Stream
+ {
+ get { return _stream; }
+ }
+
+ public DateTime ControlTime
+ {
+ get { return _controlTime; }
+ set { _controlTime = value; }
+ }
+
+ // This is a "thread safe" buffer that can be used by
+ // UnixClientTransportSink to read or send data to the stream.
+ // The buffer is "thread safe" since only one thread can
+ // use a connection at a given time.
+ public byte[] Buffer
+ {
+ get { return _buffer; }
+ }
+
+ public void Close()
+ {
+ _client.Close();
+ }
+ }
+
+}
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientTransportSinkProvider.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientTransportSinkProvider.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixClientTransportSinkProvider.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,62 @@
+//
+// System.Runtime.Remoting.Channels.Unix.UnixClientTransportSinkProvider.cs
+//
+// Author: Dietmar Maurer (dietmar at ximian.com)
+// Lluis Sanchez (lsg at ctv.es)
+//
+// 2002 (C) Copyright, Ximian, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Remoting.Channels;
+
+namespace BooBinding.Remoting
+{
+ internal class UnixClientTransportSinkProvider : IClientChannelSinkProvider
+ {
+ public UnixClientTransportSinkProvider ()
+ {
+ // what should we do here ?
+ }
+
+ public IClientChannelSinkProvider Next
+ {
+ get
+ {
+ return null;
+ }
+
+ set
+ {
+ // ignore, we are always the last in the chain
+ }
+ }
+
+ public IClientChannelSink CreateSink (IChannelSender channel, string url,
+ object remoteChannelData)
+ {
+ return new UnixClientTransportSink (url);
+ }
+ }
+}
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixListener.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixListener.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixListener.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,179 @@
+//
+// UnixListener.cs
+//
+// Authors:
+// Joe Shaw (joeshaw at novell.com)
+//
+// Copyright (C) 2004-2005 Novell, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+
+
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.IO;
+
+using Mono.Posix;
+
+namespace BooBinding.Remoting {
+
+ public class UnixListener : IDisposable {
+ bool disposed;
+ bool listening;
+ Socket server;
+ EndPoint savedEP;
+
+ void Init (UnixEndPoint ep)
+ {
+ Cleanup (ep);
+ listening = false;
+ string filename = ep.Filename;
+ if (File.Exists (filename)) {
+ Socket conn = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
+ try {
+ conn.Connect (ep);
+ conn.Close ();
+ throw new InvalidOperationException ("There's already a server listening on " + filename);
+ } catch (SocketException se) {
+ }
+ File.Delete (filename);
+ }
+
+ server = new Socket (AddressFamily.Unix, SocketType.Stream, 0);
+ server.Bind (ep);
+ savedEP = server.LocalEndPoint;
+ }
+
+ public UnixListener (string path)
+ {
+ if (!Directory.Exists (Path.GetDirectoryName (path)))
+ Directory.CreateDirectory (Path.GetDirectoryName (path));
+
+ Init (new UnixEndPoint (path));
+ }
+
+ public UnixListener (UnixEndPoint localEndPoint)
+ {
+ if (localEndPoint == null)
+ throw new ArgumentNullException ("localendPoint");
+
+ Init (localEndPoint);
+ }
+
+ public EndPoint LocalEndpoint {
+ get { return savedEP; }
+ }
+
+ protected Socket Server {
+ get { return server; }
+ }
+
+ public Socket AcceptSocket ()
+ {
+ CheckDisposed ();
+ if (!listening)
+ throw new InvalidOperationException ("Socket is not listening");
+
+ return server.Accept ();
+ }
+
+ public UnixClient AcceptUnixClient ()
+ {
+ CheckDisposed ();
+ if (!listening)
+ throw new InvalidOperationException ("Socket is not listening");
+
+ return new UnixClient (AcceptSocket ());
+ }
+
+ ~UnixListener ()
+ {
+ Dispose (false);
+ }
+
+ public bool Pending ()
+ {
+ CheckDisposed ();
+ if (!listening)
+ throw new InvalidOperationException ("Socket is not listening");
+
+ return server.Poll (1000, SelectMode.SelectRead);
+ }
+
+ public void Start ()
+ {
+ Start (5);
+ }
+
+ public void Start (int backlog)
+ {
+ CheckDisposed ();
+ if (listening)
+ return;
+
+ server.Listen (backlog);
+ listening = true;
+ }
+
+ public void Stop ()
+ {
+ CheckDisposed ();
+ Dispose (true);
+ }
+
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ protected void Dispose (bool disposing)
+ {
+ if (disposed)
+ return;
+
+ if (disposing) {
+ if (server != null)
+ server.Close ();
+
+ server = null;
+ }
+
+ disposed = true;
+ }
+
+ void CheckDisposed ()
+ {
+ if (disposed)
+ throw new ObjectDisposedException (GetType().FullName);
+ }
+
+ static void Cleanup (UnixEndPoint ep)
+ {
+ string path = ((UnixEndPoint) ep).Filename;
+ if (File.Exists (path))
+ File.Delete (path);
+ }
+ }
+
+}
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixMessageIO.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixMessageIO.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixMessageIO.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,281 @@
+// System.Runtime.Remoting.Channels.Unix.UnixMessageIO.cs
+//
+// Author: Lluis Sanchez Gual (lluis at ideary.com)
+//
+// (C) 2002 Lluis Sanchez Gual
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Collections;
+using System.IO;
+using System.Text;
+using System.Net.Sockets;
+using System.Runtime.Remoting.Channels;
+
+namespace BooBinding.Remoting
+{
+ enum MessageStatus { MethodMessage = 0, CancelSignal = 1, Unknown = 10}
+
+ internal class UnixMessageIO
+ {
+ static byte[][] _msgHeaders =
+ {
+ new byte[] { (byte)'.', (byte)'N', (byte)'E', (byte)'T', 1, 0 },
+ new byte[] { 255, 255, 255, 255, 255, 255 }
+ };
+
+ public static int DefaultStreamBufferSize = 1000;
+
+ // Identifies an incoming message
+ public static MessageStatus ReceiveMessageStatus (Stream networkStream)
+ {
+ try
+ {
+ bool[] isOnTrack = new bool[_msgHeaders.Length];
+ bool atLeastOneOnTrack = true;
+ int i = 0;
+
+ while (atLeastOneOnTrack)
+ {
+ atLeastOneOnTrack = false;
+ byte c = (byte)networkStream.ReadByte();
+ for (int n = 0; n<_msgHeaders.Length; n++)
+ {
+ if (i > 0 && !isOnTrack[n]) continue;
+
+ isOnTrack[n] = (c == _msgHeaders[n][i]);
+ if (isOnTrack[n] && (i == _msgHeaders[n].Length-1)) return (MessageStatus) n;
+ atLeastOneOnTrack = atLeastOneOnTrack || isOnTrack[n];
+ }
+ i++;
+ }
+ return MessageStatus.Unknown;
+ }
+ catch (IOException e)
+ {
+ // Stream closed
+ return MessageStatus.CancelSignal;
+ }
+ }
+
+ public static void SendMessageStream (Stream networkStream, Stream data, ITransportHeaders requestHeaders, byte[] buffer)
+ {
+ if (buffer == null) buffer = new byte[DefaultStreamBufferSize];
+
+ // Writes the message start header
+ byte[] dotnetHeader = _msgHeaders[(int) MessageStatus.MethodMessage];
+ networkStream.Write(dotnetHeader, 0, dotnetHeader.Length);
+
+ // Writes header tag (0x0000 if request stream, 0x0002 if response stream)
+ if(requestHeaders[CommonTransportKeys.RequestUri]!=null) buffer [0] = (byte) 0;
+ else buffer[0] = (byte) 2;
+ buffer [1] = (byte) 0 ;
+
+ // Writes ID
+ buffer [2] = (byte) 0;
+
+ // Writes assemblyID????
+ buffer [3] = (byte) 0;
+
+ // Writes the length of the stream being sent (not including the headers)
+ int num = (int)data.Length;
+ buffer [4] = (byte) num;
+ buffer [5] = (byte) (num >> 8);
+ buffer [6] = (byte) (num >> 16);
+ buffer [7] = (byte) (num >> 24);
+ networkStream.Write(buffer, 0, 8);
+
+ // Writes the message headers
+ SendHeaders (networkStream, requestHeaders, buffer);
+
+ // Writes the stream
+ if (data is MemoryStream)
+ {
+ // The copy of the stream can be optimized. The internal
+ // buffer of MemoryStream can be used.
+ MemoryStream memStream = (MemoryStream)data;
+ networkStream.Write (memStream.GetBuffer(), 0, (int)memStream.Length);
+ }
+ else
+ {
+ int nread = data.Read (buffer, 0, buffer.Length);
+ while (nread > 0)
+ {
+ networkStream.Write (buffer, 0, nread);
+ nread = data.Read (buffer, 0, buffer.Length);
+ }
+ }
+ }
+
+ private static void SendHeaders(Stream networkStream, ITransportHeaders requestHeaders, byte[] buffer)
+ {
+ // Writes the headers as a sequence of strings
+ if (networkStream != null)
+ {
+ IEnumerator e = requestHeaders.GetEnumerator();
+ while (e.MoveNext())
+ {
+ DictionaryEntry hdr = (DictionaryEntry)e.Current;
+ switch (hdr.Key.ToString())
+ {
+ case CommonTransportKeys.RequestUri:
+ buffer[0] = 4; buffer[1] = 0; buffer[2] = 1;
+ networkStream.Write(buffer, 0, 3);
+ break;
+ case "Content-Type":
+ buffer[0] = 6; buffer[1] = 0; buffer[2] = 1;
+ networkStream.Write(buffer, 0, 3);
+ break;
+ default:
+ buffer[0] = 1; buffer[1] = 0; buffer[2] = 1;
+ networkStream.Write(buffer, 0, 3);
+ SendString (networkStream, hdr.Key.ToString(), buffer);
+ break;
+ }
+ networkStream.WriteByte (1);
+ SendString (networkStream, hdr.Value.ToString(), buffer);
+ }
+ }
+ networkStream.WriteByte (0); // End of headers
+ networkStream.WriteByte (0);
+ }
+
+ public static ITransportHeaders ReceiveHeaders (Stream networkStream, byte[] buffer)
+ {
+ byte headerType;
+ headerType = (byte) networkStream.ReadByte ();
+ networkStream.ReadByte ();
+
+ TransportHeaders headers = new TransportHeaders ();
+
+ while (headerType != 0)
+ {
+ string key;
+ networkStream.ReadByte (); // byte 1
+ switch (headerType)
+ {
+ case 4: key = CommonTransportKeys.RequestUri; break;
+ case 6: key = "Content-Type"; break;
+ case 1: key = ReceiveString (networkStream, buffer); break;
+ default: throw new NotSupportedException ("Unknown header code: " + headerType);
+ }
+ networkStream.ReadByte (); // byte 1
+ headers[key] = ReceiveString (networkStream, buffer);
+
+ headerType = (byte) networkStream.ReadByte ();
+ networkStream.ReadByte ();
+ }
+
+ return headers;
+ }
+
+ public static Stream ReceiveMessageStream (Stream networkStream, out ITransportHeaders headers, byte[] buffer)
+ {
+ headers = null;
+
+ if (buffer == null) buffer = new byte[DefaultStreamBufferSize];
+
+ // Reads header tag: 0 -> Stream with headers or 2 -> Response Stream
+ byte head = (byte)networkStream.ReadByte();
+ byte c = (byte)networkStream.ReadByte();
+
+ c = (byte)networkStream.ReadByte();
+ c = (byte)networkStream.ReadByte();
+
+ // Gets the length of the data stream
+ int nr = 0;
+ while (nr < 4)
+ nr += networkStream.Read (buffer, nr, 4 - nr);
+
+ int byteCount = (buffer [0] | (buffer [1] << 8) |
+ (buffer [2] << 16) | (buffer [3] << 24));
+
+ // Reads the headers
+ headers = ReceiveHeaders (networkStream, buffer);
+
+ byte[] resultBuffer = new byte[byteCount];
+
+ nr = 0;
+ while (nr < byteCount)
+ nr += networkStream.Read (resultBuffer, nr, byteCount - nr);
+
+
+ return new MemoryStream(resultBuffer);
+ }
+
+ private static void SendString (Stream networkStream, string str, byte[] buffer)
+ {
+ // Allocates a buffer. Use the internal buffer if it is
+ // big enough. If not, create a new one.
+
+ int maxBytes = Encoding.UTF8.GetMaxByteCount(str.Length)+4; //+4 bytes for storing the string length
+ if (maxBytes > buffer.Length)
+ buffer = new byte[maxBytes];
+
+ int num = Encoding.UTF8.GetBytes (str, 0, str.Length, buffer, 4);
+
+ // store number of bytes (not number of chars!)
+
+ buffer [0] = (byte) num;
+ buffer [1] = (byte) (num >> 8);
+ buffer [2] = (byte) (num >> 16);
+ buffer [3] = (byte) (num >> 24);
+
+ // Write the string bytes
+ networkStream.Write (buffer, 0, num + 4);
+ }
+
+ private static string ReceiveString (Stream networkStream, byte[] buffer)
+ {
+ int nr = 0;
+ while (nr < 4)
+ nr += networkStream.Read (buffer, nr, 4 - nr);
+
+ // Reads the number of bytes (not chars!)
+
+ int byteCount = (buffer [0] | (buffer [1] << 8) |
+ (buffer [2] << 16) | (buffer [3] << 24));
+
+ if (byteCount == 0) return string.Empty;
+
+ // Allocates a buffer of the correct size. Use the
+ // internal buffer if it is big enough
+
+ if (byteCount > buffer.Length)
+ buffer = new byte[byteCount];
+
+ // Reads the string
+
+ nr = 0;
+ while (nr < byteCount)
+ nr += networkStream.Read (buffer, nr, byteCount - nr);
+
+ char[] chars = Encoding.UTF8.GetChars(buffer, 0, byteCount);
+
+ return new string(chars);
+ }
+
+ }
+}
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixServerChannel.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixServerChannel.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixServerChannel.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,328 @@
+//
+// System.Runtime.Remoting.Channels.Unix.UnixServerChannel.cs
+//
+// Author: Rodrigo Moya (rodrigo at ximian.com)
+// Lluis Sanchez Gual (lluis at ideary.com)
+//
+// 2002 (C) Copyright, Ximian, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Runtime.Remoting.Messaging;
+using System.Text.RegularExpressions;
+using System.Net.Sockets;
+using System.Net;
+using System.Threading;
+using System.IO;
+using System.Runtime.Remoting.Channels;
+
+namespace BooBinding.Remoting
+{
+ public class UnixServerChannel : IChannelReceiver, IChannel
+ {
+ string path = null;
+ string name = "unix";
+
+ int priority = 1;
+ bool supressChannelData = false;
+ bool useIpAddress = false;
+
+ IPAddress bindAddress = IPAddress.Any;
+ Thread server_thread = null;
+ UnixListener listener;
+ UnixServerTransportSink sink;
+ ChannelDataStore channel_data;
+ int _maxConcurrentConnections = 100;
+ ArrayList _activeConnections = new ArrayList();
+
+
+ void Init (IServerChannelSinkProvider serverSinkProvider)
+ {
+ if (serverSinkProvider == null)
+ {
+ serverSinkProvider = new BinaryServerFormatterSinkProvider ();
+ }
+
+ // Gets channel data from the chain of channel providers
+
+ channel_data = new ChannelDataStore (null);
+ IServerChannelSinkProvider provider = serverSinkProvider;
+ while (provider != null)
+ {
+ provider.GetChannelData(channel_data);
+ provider = provider.Next;
+ }
+
+ // Creates the sink chain that will process all incoming messages
+
+ IServerChannelSink next_sink = ChannelServices.CreateServerChannelSinkChain (serverSinkProvider, this);
+ sink = new UnixServerTransportSink (next_sink);
+ }
+
+ public UnixServerChannel (string path)
+ {
+ this.path = path;
+ Init (null);
+ }
+
+ public UnixServerChannel (IDictionary properties,
+ IServerChannelSinkProvider serverSinkProvider)
+ {
+ foreach(DictionaryEntry property in properties)
+ {
+ switch((string)property.Key)
+ {
+ case "path":
+ path = property.Value as string;
+ break;
+ case "priority":
+ priority = Convert.ToInt32(property.Value);
+ break;
+ case "supressChannelData":
+ supressChannelData = Convert.ToBoolean (property.Value);
+ break;
+ }
+ }
+ Init (serverSinkProvider);
+ }
+
+ public UnixServerChannel (string name, string path,
+ IServerChannelSinkProvider serverSinkProvider)
+ {
+ this.name = name;
+ this.path = path;
+ Init (serverSinkProvider);
+ }
+
+ public UnixServerChannel (string name, string path)
+ {
+ this.name = name;
+ this.path = path;
+ Init (null);
+ }
+
+ public object ChannelData
+ {
+ get {
+ if (supressChannelData) return null;
+ else return channel_data;
+ }
+ }
+
+ public string ChannelName
+ {
+ get {
+ return name;
+ }
+ }
+
+ public int ChannelPriority
+ {
+ get {
+ return priority;
+ }
+ }
+
+ public string GetChannelUri ()
+ {
+ return "unix://" + path;
+ }
+
+ public string[] GetUrlsForUri (string uri)
+ {
+ if (!uri.StartsWith ("/")) uri = "/" + uri;
+
+ string [] chnl_uris = channel_data.ChannelUris;
+ string [] result = new String [chnl_uris.Length];
+
+ for (int i = 0; i < chnl_uris.Length; i++)
+ result [i] = chnl_uris [i] + uri;
+
+ return result;
+ }
+
+ public string Parse (string url, out string objectURI)
+ {
+ return UnixChannel.ParseUnixURL (url, out objectURI);
+ }
+
+ void WaitForConnections ()
+ {
+ try
+ {
+ while (true)
+ {
+ UnixClient client = listener.AcceptUnixClient ();
+ CreateListenerConnection (client);
+ }
+ }
+ catch
+ {}
+ }
+
+ internal void CreateListenerConnection (UnixClient client)
+ {
+ lock (_activeConnections)
+ {
+ if (_activeConnections.Count >= _maxConcurrentConnections)
+ Monitor.Wait (_activeConnections);
+
+ if (server_thread == null) return; // Server was stopped while waiting
+
+ ClientConnection reader = new ClientConnection (this, client, sink);
+ Thread thread = new Thread (new ThreadStart (reader.ProcessMessages));
+ thread.Start();
+ thread.IsBackground = true;
+ _activeConnections.Add (thread);
+ }
+ }
+
+ internal void ReleaseConnection (Thread thread)
+ {
+ lock (_activeConnections)
+ {
+ _activeConnections.Remove (thread);
+ Monitor.Pulse (_activeConnections);
+ }
+ }
+
+ public void StartListening (object data)
+ {
+ listener = new UnixListener (path);
+ Mono.Unix.Syscall.chmod (path,
+ Mono.Unix.FilePermissions.S_IRUSR |
+ Mono.Unix.FilePermissions.S_IWUSR |
+ Mono.Unix.FilePermissions.S_IRGRP |
+ Mono.Unix.FilePermissions.S_IWGRP |
+ Mono.Unix.FilePermissions.S_IROTH |
+ Mono.Unix.FilePermissions.S_IWOTH);
+
+ if (server_thread == null)
+ {
+ listener.Start ();
+
+ string[] uris = new String [1];
+ uris = new String [1];
+ uris [0] = GetChannelUri ();
+ channel_data.ChannelUris = uris;
+
+ server_thread = new Thread (new ThreadStart (WaitForConnections));
+ server_thread.IsBackground = true;
+ server_thread.Start ();
+ }
+ }
+
+ public void StopListening (object data)
+ {
+ if (server_thread == null) return;
+
+ lock (_activeConnections)
+ {
+ server_thread.Abort ();
+ server_thread = null;
+ listener.Stop ();
+
+ foreach (Thread thread in _activeConnections)
+ thread.Abort();
+
+ _activeConnections.Clear();
+ Monitor.PulseAll (_activeConnections);
+ }
+ }
+ }
+
+ class ClientConnection
+ {
+ UnixClient _client;
+ UnixServerTransportSink _sink;
+ Stream _stream;
+ UnixServerChannel _serverChannel;
+
+ byte[] _buffer = new byte[UnixMessageIO.DefaultStreamBufferSize];
+
+ public ClientConnection (UnixServerChannel serverChannel, UnixClient client, UnixServerTransportSink sink)
+ {
+ _serverChannel = serverChannel;
+ _client = client;
+ _sink = sink;
+ }
+
+ public UnixClient Client {
+ get { return _client; }
+ }
+
+ public Stream Stream
+ {
+ get { return _stream; }
+ }
+
+ public byte[] Buffer
+ {
+ get { return _buffer; }
+ }
+
+ public void ProcessMessages()
+ {
+ _stream = _client.GetStream();
+
+ try
+ {
+ bool end = false;
+ while (!end)
+ {
+ MessageStatus type = UnixMessageIO.ReceiveMessageStatus (_stream);
+
+ switch (type)
+ {
+ case MessageStatus.MethodMessage:
+ _sink.InternalProcessMessage (this);
+ break;
+
+ case MessageStatus.CancelSignal:
+ end = true;
+ break;
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ // Console.WriteLine (ex);
+ }
+ finally
+ {
+ _stream.Close();
+ _serverChannel.ReleaseConnection (Thread.CurrentThread);
+ }
+ }
+
+ public bool IsLocal
+ {
+ get
+ {
+ return true;
+ }
+ }
+ }
+}
Added: trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixServerTransportSink.cs
===================================================================
--- trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixServerTransportSink.cs 2005-04-27 22:58:24 UTC (rev 2488)
+++ trunk/MonoDevelop/Extras/BooBinding/Remoting/UnixServerTransportSink.cs 2005-04-28 02:38:46 UTC (rev 2489)
@@ -0,0 +1,132 @@
+//
+// System.Runtime.Remoting.Channels.Unix.UnixServerTransportSink.cs
+//
+// Author: Rodrigo Moya (rodrigo at ximian.com)
+// Lluis Sanchez Gual (lsg at ctv.es)
+//
+// 2002 (C) Copyright, Ximian, Inc.
+//
+
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections;
+using System.Runtime.Remoting.Messaging;
+using System.IO;
+using System.Runtime.Remoting.Channels;
+using Mono.Posix;
+
+namespace BooBinding.Remoting
+{
+ internal class UnixServerTransportSink : IServerChannelSink, IChannelSinkBase
+ {
+ IServerChannelSink next_sink;
+
+ public UnixServerTransportSink (IServerChannelSink next)
+ {
+ next_sink = next;
+ }
+
+ public IServerChannelSink NextChannelSink
+ {
+ get
+ {
+ return next_sink;
+ }
+ }
+
+ public IDictionary Properties
+ {
+ get
+ {
+ if (next_sink != null) return next_sink.Properties;
+ else return null;
+ }
+ }
+
+ public void AsyncProcessResponse (IServerResponseChannelSinkStack sinkStack, object state,
+ IMessage msg, ITransportHeaders headers, Stream responseStream)
+ {
+ ClientConnection connection = (ClientConnection)state;
+ UnixMessageIO.SendMessageStream (connection.Stream, responseStream, headers, connection.Buffer);
+ }
+
+ public Stream GetResponseStream (IServerResponseChannelSinkStack sinkStack, object state,
+ IMessage msg, ITransportHeaders headers)
+ {
+ return null;
+ }
+
+ public ServerProcessing ProcessMessage (IServerChannelSinkStack sinkStack,
+ IMessage requestMsg,
+ ITransportHeaders requestHeaders,
+ Stream requestStream,
+ out IMessage responseMsg,
+ out ITransportHeaders responseHeaders,
+ out Stream responseStream)
+ {
+ // this is the first sink, and UnixServerChannel does not call it.
+ throw new NotSupportedException ();
+ }
+
+ internal void InternalProcessMessage (ClientConnection connection)
+ {
+ // Reads the headers and the request stream
+
+ Stream requestStream;
+ ITransportHeaders requestHeaders;
+
+ requestStream = UnixMessageIO.ReceiveMessageStream (connection.Stream, out requestHeaders, connection.Buffer);
+
+ try {
+ PeerCred cred = connection.Client.PeerCredential;
+ requestHeaders["__uid"] = cred.UserID;
+ } catch (Exception e) {
+ Console.WriteLine ("Couldn't get the peer cred: " + e);
+ }
+
+ // Pushes the connection object together with the sink. This information
+ // will be used for sending the response in an async call.
+
+ ServerChannelSinkStack sinkStack = new ServerChannelSinkStack();
+ sinkStack.Push(this, connection);
+
+ ITransportHeaders responseHeaders;
+ Stream responseStream;
+ IMessage responseMsg;
+
+ ServerProcessing proc = next_sink.ProcessMessage(sinkStack, null, requestHeaders, requestStream, out responseMsg, out responseHeaders, out responseStream);
+
+ switch (proc)
+ {
+ case ServerProcessing.Complete:
+ UnixMessageIO.SendMessageStream (connection.Stream, responseStream, responseHeaders, connection.Buffer);
+ break;
+
+ case ServerProcessing.Async:
+ case ServerProcessing.OneWay:
+ break;
+ }
+ }
+ }
+}
+
More information about the Monodevelop-patches-list
mailing list