|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
pic_options='-fPIC'
;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
pic_options='-DDLL_EXPORT'
;;
i?86-apple-darwin*|arm-apple-darwin*)
--- /dev/null
+#
+# Appveyor configuration file for CI build of Mono on Windows (under Cygwin)
+#
+# For further details see http://www.appveyor.com
+#
+
+# Use 'unstable' Appveyor build worker image as Appveyor have added Cygwin to this for us
+os: Unstable
+
+#
+# Custom environment variables
+#
+environment:
+ global:
+ CYG_ROOT: C:/cygwin
+ CYG_MIRROR: http://cygwin.mirror.constant.com
+ CYG_CACHE: C:/cygwin/var/cache/setup
+ NSIS_ROOT: C:\nsis
+
+#
+# Initialisation prior to pulling the Mono repository
+#
+init:
+ - 'echo Building Mono for Windows'
+ - 'echo System architecture: %PLATFORM%'
+ - 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
+ - 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
+# Attempt to ensure we don't try to convert line endings to Win32 CRLF as this will cause build to fail
+ - 'git config --global core.autocrlf input'
+
+#
+# Install needed build dependencies
+#
+install:
+# NOTE: Already installed on current Appveyor unstable image
+# - 'echo Retrieving Cygwin'
+# - 'appveyor DownloadFile http://cygwin.com/setup-x86.exe -FileName %CYGROOT%/setup-x86.exe'
+ - 'echo Setting up Cygwin dependencies'
+ - '%CYG_ROOT%\setup-x86.exe -qnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P autoconf -P automake -P bison -P gcc-core -P gcc-g++ -P mingw-runtime -P mingw-binutils -P mingw-gcc-core -P mingw-gcc-g++ -P mingw-pthreads -P mingw-w32api -P libtool -P make -P python -P gettext-devel -P gettext -P intltool -P libiconv -P pkg-config -P git -P wget -P curl > NUL'
+ - 'echo Check Cygwin setup'
+ - '%CYG_ROOT%/bin/bash -lc "cygcheck -dc cygwin"'
+ - 'echo Done setting up Cygwin'
+ - 'echo Retrieving NSIS'
+ - 'appveyor DownloadFile "http://sunet.dl.sourceforge.net/project/nsis/NSIS 2/2.46/nsis-2.46-setup.exe" -FileName nsissetup.exe'
+ - 'echo Setting up NSIS'
+ - 'nsissetup.exe /S /D=%NSIS_ROOT%'
+ - 'echo Done setting up NSIS'
+
+#
+# NOTE: msbuild doesn't work at present so use Cygwin to build
+#
+#build:
+# project: C:\projects\mono\msvc\mono.sln
+# verbosity: detailed
+
+# Cygwin build script
+#
+# NOTES:
+#
+# The stdin/stdout file descriptor appears not to be valid for the Appveyor
+# build which causes failures as certain functions attempt to redirect
+# default file handles. Ensure a dummy file descriptor is opened with exec.
+#
+build_script:
+ - cmd: 'echo Cygwin root is: %CYG_ROOT%'
+ - cmd: 'echo Build folder is: %APPVEYOR_BUILD_FOLDER%'
+ - cmd: 'echo Repo build branch is: %APPVEYOR_REPO_BRANCH%'
+ - cmd: 'echo Repo build commit is: %APPVEYOR_REPO_COMMIT%'
+ - cmd: 'echo Autogen running...'
+ - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; NOCONFIGURE=1 ./autogen.sh --prefix=/usr/local --with-preview=yes"'
+ - cmd: 'echo Configure running...'
+ - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; ./configure --host=i686-pc-mingw32"'
+ - cmd: 'echo Pulling monolite latest...'
+ - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make get-monolite-latest"'
+ - cmd: 'echo Make running...'
+ - cmd: '%CYG_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make"'
+ - cmd: 'echo Installing...'
+ - cmd: 'mkdir %APPVEYOR_BUILD_FOLDER%\install'
+ - cmd: '%CYG_ROOT%/bin/bash --login -lc "export CYGWIN=winsymlinks:native; mount \"$APPVEYOR_BUILD_FOLDER\install\" /usr/local; cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make install; umount /usr/local"'
+# - cmd: 'echo Building package...'
+# - cmd: 'cd %APPVEYOR_BUILD_FOLDER%'
+# - cmd: '%NSIS_ROOT%\makensis /DMILESTONE=%APPVEYOR_REPO_BRANCH% /DSOURCE_INSTALL_DIR=%APPVEYOR_BUILD_FOLDER\install\*.* /DBUILDNUM=%APPVEYOR_BUILD_VERSION% monowiz.win32.nsi'
+# - cmd: 'Building distribution...'
+# - cmd: '%CYG_ROOT%/bin/bash -lc "export CYGWIN=winsymlinks:native; cd $APPVEYOR_BUILD_FOLDER; exec 0</dev/null; make dist"'
+
+#
+# Disable tests for now
+#
+test: off
+
+#
+# NOTE: Currently this is the Mono installation tree. In future we will create an installation package artifact.
+# It has to be relative to the project path. Thus we have installed to within the build tree.
+#
+artifacts:
+ - path: install
+ name: mono-binaries
+ type: zip
# Process this file with autoconf to produce a configure script.
#AC_PREREQ([2.62])
-AC_INIT(mono, [3.10.1],
+AC_INIT(mono, [3.12.1],
[http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono])
AC_CONFIG_SRCDIR([README.md])
fi
CFLAGS="$CFLAGS -g $WARN"
CFLAGS_FOR_LIBGC="$CFLAGS_FOR_LIBGC -g"
+CPPFLAGS="$CPPFLAGS -g $WARN"
# Where's the 'mcs' source tree?
if test -d $srcdir/mcs; then
# Should be something like '2.6' or '2.7svn'
llvm_version=`$LLVM_CONFIG --version`
- major_version=`echo $llvm_version | cut -c 1`
- minor_version=`echo $llvm_version | cut -c 3`
llvm_api_version=`$LLVM_CONFIG --mono-api-version 2>/dev/null`
AC_MSG_CHECKING(LLVM version)
AC_MSG_RESULT($llvm_version)
AC_MSG_ERROR([Compiling with stock LLVM is not supported, please use the Mono LLVM repo at https://github.com/mono/llvm, with the GIT branch which matches this version of mono, i.e. 'mono-2-10' for Mono 2.10.])
fi
- AC_DEFINE_UNQUOTED(LLVM_MAJOR_VERSION, $major_version, [Major version of LLVM libraries])
- AC_DEFINE_UNQUOTED(LLVM_MINOR_VERSION, $minor_version, [Minor version of LLVM libraries])
AC_DEFINE_UNQUOTED(LLVM_VERSION, "$llvm_version", [Full version of LLVM libraties])
- # Have to pass these on the command line since mini-llvm-cpp.h already includes
- # llvm's config.h
- LLVM_CXXFLAGS="$LLVM_CXXFLAGS -DLLVM_MAJOR_VERSION=$major_version -DLLVM_MINOR_VERSION=$minor_version"
-
AC_SUBST(LLVM_CFLAGS)
AC_SUBST(LLVM_CXXFLAGS)
AC_SUBST(LLVM_LIBS)
|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
pic_options='-fPIC'
;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
pic_options='-DDLL_EXPORT'
;;
i?86-apple-darwin*|arm-apple-darwin*)
|amd64-*-freebsd*|i?86-*-freebsd*|ia64-*-freebsd*|arm*-*-linux*|sparc*-*-linux*|mips*-*-linux*|x86_64-apple-darwin*|aarch64*)
pic_options='-fPIC'
;;
-?86-pc-cygwin*|i?86-pc-cygwin*)
+?86-pc-cygwin*|i?86-pc-cygwin*|i?86-pc-mingw32*)
pic_options='-DDLL_EXPORT'
;;
i?86-apple-darwin*|arm-apple-darwin*)
# define GC_LINUX_THREADS
#endif
#if defined(WIN32_THREADS)
-# define GC_WIN32_THREADS
+# define GC_WIN32_THREADS 1
#endif
#if defined(USE_LD_WRAP)
# define GC_USE_LD_WRAP
using System;
using System.Drawing;
+using System.Diagnostics;
+using System.IO;
namespace System.Windows.Forms
{
+ /// <summary>
+ /// http://msdn.microsoft.com/en-us/library/System.Windows.Forms.Help(v=vs.110).aspx
+ /// </summary>
public class Help
{
#region Constructor
#region Public Static Methods
public static void ShowHelp (Control parent, string url)
{
- ShowHelp(parent, url, HelpNavigator.TableOfContents, null);
+ ShowHelp (parent, url, null);
}
public static void ShowHelp (Control parent, string url, HelpNavigator navigator)
public static void ShowHelp (Control parent, string url, string keyword)
{
- if (keyword == null || keyword == String.Empty)
- ShowHelp (parent, url, HelpNavigator.TableOfContents, null);
- ShowHelp (parent, url, HelpNavigator.Topic, keyword);
+ ShowHelpTopic (url, keyword);
}
public static void ShowHelpIndex (Control parent, string url)
{
}
#endregion // Public Static Methods
+
+ /// <summary>
+ /// Show a help file and topic using a help viewer
+ /// </summary>
+ /// <param name="helpFile">path to a .chm help file</param>
+ /// <param name="helpTopic">path to a topic in helpFile, or null</param>
+ private static void ShowHelpTopic (string helpFile, string helpTopic)
+ {
+ if (helpFile == null)
+ throw new ArgumentNullException ();
+ if (helpFile == String.Empty)
+ throw new ArgumentException ();
+
+ // Use forward slashes in helpFile path if needed
+ helpFile = helpFile.Replace (@"\", Path.DirectorySeparatorChar.ToString ());
+
+ string helpViewer = Environment.GetEnvironmentVariable ("MONO_HELP_VIEWER") ?? "chmsee";
+ string arguments = String.Format ("\"{0}\"", helpFile);
+ if (!String.IsNullOrEmpty (helpTopic)) {
+ if (!helpTopic.StartsWith ("/"))
+ helpTopic = "/" + helpTopic;
+ helpTopic = helpTopic.TrimEnd (' ');
+ arguments = String.Format ("\"{0}::{1}\"", helpFile, helpTopic);
+ }
+
+ try {
+ RunNonblockingProcess (helpViewer, arguments);
+ } catch (Exception e) {
+ // Don't crash if the help viewer couldn't be launched. There
+ // won't be an exception thrown if the help viewer can't find
+ // the help file; it's up to the help viewer to display such an error.
+ string message = String.Format ("The help viewer could not load. Maybe you don't have {0} installed or haven't set MONO_HELP_VIEWER. The specific error message was: {1}", helpViewer, e.Message);
+ Console.Error.WriteLine (message);
+ MessageBox.Show (message);
+ }
+ }
+
+ /// <remarks>
+ /// throws exception from Process.Start() if there was a problem starting
+ /// </remarks>
+ private static void RunNonblockingProcess (string command, string arguments)
+ {
+ using (Process process = new Process ()) {
+ process.StartInfo.FileName = command;
+ process.StartInfo.Arguments = arguments;
+ process.StartInfo.UseShellExecute = false;
+
+ process.Start ();
+ }
+ }
}
}
Comm.Append ((byte) 0x00); // no param meta data name
Comm.Append ((byte) 0x00); // no status flags
+
+ // Convert BigNVarChar values larger than 4000 chars to nvarchar(max)
+ // Need to do this here so WritePreparedParameterInfo emit the
+ // correct data type
+ foreach (TdsMetaParameter param2 in parameters) {
+ var colType = param2.GetMetaType ();
+
+ if (colType == TdsColumnType.BigNVarChar) {
+ int size = param2.GetActualSize ();
+ if ((size >> 1) > 4000)
+ param2.Size = -1;
+ }
+ }
// Write sql as a parameter value - UCS2
TdsMetaParameter param = new TdsMetaParameter ("sql",
$(MAKE) csproj-local intermediate=plaincore/
endif
endif
+
+#
+# Android TimeZoneInfo testing....
+#
+
+tzi.exe: ../corlib/System/AndroidPlatform.cs $(wildcard System/TimeZone*.cs) ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs
+ mcs /debug+ /out:$@ /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" $^
+
+android-pull-tzdb:
+ mkdir -p android/tzdb/usr/share/zoneinfo
+ mkdir -p android/tzdb/misc/zoneinfo/zoneinfo
+ android_root=`adb shell echo '$$ANDROID_ROOT' | tr -d "\r"` ; \
+ android_data=`adb shell echo '$$ANDROID_DATA' | tr -d "\r"` ; \
+ adb $(ADB_TARGET) pull $$android_root/usr/share/zoneinfo android/tzdb/usr/share/zoneinfo ; \
+ adb $(ADB_TARGET) pull $$android_data/misc/zoneinfo/tzdata android/tzdb/misc/zoneinfo
+ mkdir -p android/tzdb/
+
+android-dump-tzdata: tzi.exe android-pull-tzdb
+ __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe -o android/tzdata
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System
{
- public sealed partial class TimeZoneInfo {
+#if NET_4_0 || !INSIDE_CORLIB
+ public
+#endif
+ sealed partial class TimeZoneInfo {
[SerializableAttribute]
#if MOBILE
[TypeForwardedFrom (Consts.AssemblySystem_Core)]
tzdataPath, offset, length, r, buffer.Length));
}
+ TimeZoneInfo.DumpTimeZoneDataToFile (id, buffer);
return buffer;
}
}
* Compile:
* mcs /debug+ /out:tzi.exe /unsafe "/d:INSIDE_CORLIB;MONODROID;NET_4_0;LIBC;SELF_TEST" ../corlib/System/AndroidPlatform.cs System/TimeZone*.cs ../../build/common/Consts.cs ../Mono.Options/Mono.Options/Options.cs
* Prep:
- * mkdir -p usr/share/zoneinfo
- * mkdir -p misc/zoneinfo/zoneinfo
+ * mkdir -p android/tzdb/usr/share/zoneinfo
+ * mkdir -p android/tzdb/misc/zoneinfo/zoneinfo
* android_root=`adb shell echo '$ANDROID_ROOT' | tr -d "\r"`
* android_data=`adb shell echo '$ANDROID_DATA' | tr -d "\r"`
- * adb pull $android_root/usr/share/zoneinfo usr/share/zoneinfo
- * adb pull $android_data/misc/zoneinfo/tzdata misc/zoneinfo
+ * adb pull $android_root/usr/share/zoneinfo android/tzdb/usr/share/zoneinfo
+ * adb pull $android_data/misc/zoneinfo/tzdata android/tzdb/misc/zoneinfo
* Run:
+ * # Dump all timezone names
* __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe --offset=1969-01-01
+ *
+ * # Dump TimeZone data to files under path `tzdata`
+ * __XA_OVERRIDE_TIMEZONE_ID__=America/New_York ANDROID_ROOT=`pwd` ANDROID_DATA=`pwd` mono --debug tzi.exe -o android/tzdata
+ *
+ * # Dump TimeZone rules for specific timezone data (as dumped above)
+ * mono tzi.exe --offset=2012-10-24 -i=tzdata/Asia/Amman
*/
static void Main (string[] args)
{
DateTime? offset = null;
Func<IAndroidTimeZoneDB> c = () => GetDefaultTimeZoneDB ();
+ bool dump_rules = false;
Mono.Options.OptionSet p = null;
p = new Mono.Options.OptionSet () {
+ { "i=",
+ "TimeZone data {FILE} to parse and dump",
+ v => DumpTimeZoneFile (v, offset)
+ },
+ { "o=",
+ "Write TimeZone data files to {PATH}",
+ v => TimeZoneInfo.TimeZoneDataExportPath = v
+ },
{ "T=", "Create AndroidTzData from {PATH}.", v => {
c = () => new AndroidTzData (v);
} },
offset = DateTime.Parse (v);
Console.WriteLine ("Using DateTime Offset: {0}", offset);
} },
+ { "R|dump-rules",
+ "Show timezone info offset for DateTime {OFFSET}.",
+ v => dump_rules = v != null },
{ "help", "Show this message and exit", v => {
p.WriteOptionDescriptions (Console.Out);
Environment.Exit (0);
if (offset.HasValue) {
Console.Write ("From Offset: {0}", zone.GetUtcOffset (offset.Value));
}
+ if (dump_rules) {
+ WriteZoneRules (zone);
+ }
}
else {
Console.Write (" ERROR:null");
Console.WriteLine ();
}
}
+
+ static void WriteZoneRules (TimeZoneInfo zone)
+ {
+ var rules = zone.GetAdjustmentRules ();
+ for (int i = 0; i < rules.Length; ++i) {
+ var rule = rules [i];
+ Console.WriteLine ();
+ Console.Write ("\tAdjustmentRules[{0,3}]: DaylightDelta={1}; DateStart={2:yyyy-MM}; DateEnd={3:yyyy-MM}; DaylightTransitionStart={4:D2}-{5:D2}T{6}; DaylightTransitionEnd={7:D2}-{8:D2}T{9}",
+ i,
+ rule.DaylightDelta,
+ rule.DateStart, rule.DateEnd,
+ rule.DaylightTransitionStart.Month, rule.DaylightTransitionStart.Day, rule.DaylightTransitionStart.TimeOfDay.TimeOfDay,
+ rule.DaylightTransitionEnd.Month, rule.DaylightTransitionEnd.Day, rule.DaylightTransitionEnd.TimeOfDay.TimeOfDay);
+ }
+ }
+
+ static void DumpTimeZoneFile (string path, DateTime? time)
+ {
+ var buffer = File.ReadAllBytes (path);
+ var zone = ParseTZBuffer (path, buffer, buffer.Length);
+ Console.Write ("Rules for: {0}", path);
+ WriteZoneRules (zone);
+ Console.WriteLine ();
+ if (time.HasValue) {
+ var offset = zone.GetUtcOffset (time.Value);
+ var isDst = zone.IsDaylightSavingTime (time.Value);
+ Console.WriteLine ("\tDate({0}): Offset({1}) IsDST({2})", time.Value, offset, isDst);
+ }
+ }
+#endif
+ }
+
+#if SELF_TEST
+ static string TimeZoneDataExportPath;
+#endif
+
+ internal static void DumpTimeZoneDataToFile (string id, byte[] buffer)
+ {
+#if SELF_TEST
+ int p = id.LastIndexOf ('/');
+ var o = Path.Combine (TimeZoneDataExportPath,
+ p >= 0 ? id.Substring (0, p) : id);
+ if (p >= 0)
+ o = Path.Combine (o, id.Substring (p+1));
+ Directory.CreateDirectory (Path.GetDirectoryName (o));
+ using (var f = File.OpenWrite (o))
+ f.Write (buffer, 0, buffer.Length);
#endif
}
}
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
using System.Collections.Generic;
using System.Globalization;
namespace System
{
- public partial class TimeZoneInfo
+#if NET_4_0 || !INSIDE_CORLIB
+ public
+#endif
+ partial class TimeZoneInfo
{
public static TimeZoneInfo FromSerializedString (string source)
{
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#if INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
namespace System
{
- public sealed partial class TimeZoneInfo
+#if NET_4_0 || !INSIDE_CORLIB
+ public
+#endif
+ sealed partial class TimeZoneInfo
{
[SerializableAttribute]
#if MOBILE
[assembly:TypeForwardedTo (typeof(TimeZoneInfo))]
-#elif (INSIDE_CORLIB && NET_4_0) || (!INSIDE_CORLIB && (NET_3_5 && !NET_4_0 && !MOBILE))
+#elif INSIDE_CORLIB || (NET_3_5 && !NET_4_0 && !MOBILE)
using System.Collections.Generic;
using System.Collections.ObjectModel;
[TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
#endif
[SerializableAttribute]
- public sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
+#if NET_4_0 || !INSIDE_CORLIB
+ public
+#endif
+ sealed partial class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
{
TimeSpan baseUtcOffset;
public TimeSpan BaseUtcOffset {
}
}
+ /*
+ TimeZone transitions are stored when there is a change on the base offset.
+ */
+ private List<KeyValuePair<DateTime, TimeType>> transitions;
+
static TimeZoneInfo CreateLocal ()
{
#if MONODROID
return BuildFromStream ("Local", stream);
}
#elif LIBC
+ var tz = Environment.GetEnvironmentVariable ("TZ");
+ if (tz != null) {
+ if (tz == String.Empty)
+ return Utc;
+ try {
+ return FindSystemTimeZoneByFileName (tz, Path.Combine (TimeZoneDirectory, tz));
+ } catch {
+ return Utc;
+ }
+ }
+
try {
return FindSystemTimeZoneByFileName ("Local", "/etc/localtime");
} catch {
if (dateTime.Kind == DateTimeKind.Utc)
return dateTime;
- //FIXME: do not rely on DateTime implementation !
- return DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc);
+ return ConvertTimeToUtc (dateTime, TimeZoneInfo.Local);
}
public static DateTime ConvertTimeToUtc (DateTime dateTime, TimeZoneInfo sourceTimeZone)
if (sourceTimeZone.IsInvalidTime (dateTime))
throw new ArgumentException ("dateTime parameter is an invalid time");
- if (dateTime.Kind == DateTimeKind.Utc && sourceTimeZone == TimeZoneInfo.Utc)
- return dateTime;
-
if (dateTime.Kind == DateTimeKind.Utc)
return dateTime;
- if (dateTime.Kind == DateTimeKind.Local)
- return ConvertTimeToUtc (dateTime);
-
if (sourceTimeZone.IsAmbiguousTime (dateTime) || !sourceTimeZone.IsDaylightSavingTime (dateTime))
return DateTime.SpecifyKind (dateTime - sourceTimeZone.BaseUtcOffset, DateTimeKind.Utc);
else {
public TimeSpan GetUtcOffset (DateTime dateTime)
{
- if (IsDaylightSavingTime (dateTime)) {
- AdjustmentRule rule = GetApplicableRule (dateTime);
- if (rule != null)
- return BaseUtcOffset + rule.DaylightDelta;
- }
-
- return BaseUtcOffset;
+ bool isDST;
+ return GetUtcOffset (dateTime, out isDST);
}
public TimeSpan GetUtcOffset (DateTimeOffset dateTimeOffset)
throw new NotImplementedException ();
}
+ private TimeSpan GetUtcOffset (DateTime dateTime, out bool isDST)
+ {
+ isDST = false;
+
+ TimeZoneInfo tz = this;
+ if (dateTime.Kind == DateTimeKind.Utc)
+ tz = TimeZoneInfo.Utc;
+
+ if (dateTime.Kind == DateTimeKind.Local)
+ tz = TimeZoneInfo.Local;
+
+ bool isTzDst;
+ var tzOffset = GetUtcOffset (dateTime, tz, out isTzDst);
+
+ if (tz == this) {
+ isDST = isTzDst;
+ return tzOffset;
+ }
+
+ var utcTicks = dateTime.Ticks - tzOffset.Ticks;
+ if (utcTicks < 0 || utcTicks > DateTime.MaxValue.Ticks)
+ return BaseUtcOffset;
+
+ var utcDateTime = new DateTime (utcTicks, DateTimeKind.Utc);
+
+ return GetUtcOffset (utcDateTime, this, out isDST);
+ }
+
+ private static TimeSpan GetUtcOffset (DateTime dateTime, TimeZoneInfo tz, out bool isDST)
+ {
+ if (dateTime.Kind == DateTimeKind.Local && tz != TimeZoneInfo.Local)
+ throw new Exception ();
+
+ isDST = false;
+
+ if (tz == TimeZoneInfo.Utc)
+ return TimeSpan.Zero;
+
+ TimeSpan offset;
+ if (tz.TryGetTransitionOffset(dateTime, out offset, out isDST))
+ return offset;
+
+ if (dateTime.Kind == DateTimeKind.Utc) {
+ var utcRule = tz.GetApplicableRule (dateTime);
+ if (utcRule != null && tz.IsInDST (utcRule, dateTime)) {
+ isDST = true;
+ return tz.BaseUtcOffset + utcRule.DaylightDelta;
+ }
+
+ return tz.BaseUtcOffset;
+ }
+
+ var stdTicks = dateTime.Ticks - tz.BaseUtcOffset.Ticks;
+ if (stdTicks < 0 || stdTicks > DateTime.MaxValue.Ticks)
+ return tz.BaseUtcOffset;
+
+ var stdUtcDateTime = new DateTime (stdTicks, DateTimeKind.Utc);
+ var tzRule = tz.GetApplicableRule (stdUtcDateTime);
+
+ DateTime dstUtcDateTime = DateTime.MinValue;
+ if (tzRule != null) {
+ var dstTicks = stdUtcDateTime.Ticks - tzRule.DaylightDelta.Ticks;
+ if (dstTicks < 0 || dstTicks > DateTime.MaxValue.Ticks)
+ return tz.BaseUtcOffset;
+
+ dstUtcDateTime = new DateTime (dstTicks, DateTimeKind.Utc);
+ }
+
+ if (tzRule != null && tz.IsInDST (tzRule, stdUtcDateTime) && tz.IsInDST (tzRule, dstUtcDateTime)) {
+ isDST = true;
+ return tz.BaseUtcOffset + tzRule.DaylightDelta;
+ }
+
+ return tz.BaseUtcOffset;
+ }
+
public bool HasSameRules (TimeZoneInfo other)
{
if (other == null)
throw new NotImplementedException ();
}
+ private bool IsInDST (AdjustmentRule rule, DateTime dateTime)
+ {
+ // Check whether we're in the dateTime year's DST period
+ if (IsInDSTForYear (rule, dateTime, dateTime.Year))
+ return true;
+
+ // We might be in the dateTime previous year's DST period
+ return IsInDSTForYear (rule, dateTime, dateTime.Year - 1);
+ }
+
bool IsInDSTForYear (AdjustmentRule rule, DateTime dateTime, int year)
{
DateTime DST_start = TransitionPoint (rule.DaylightTransitionStart, year);
if (!SupportsDaylightSavingTime)
return false;
-
- //FIXME: do not rely on DateTime implementation !
- if ((dateTime.Kind == DateTimeKind.Local || dateTime.Kind == DateTimeKind.Unspecified) && this == TimeZoneInfo.Local)
- return dateTime.IsDaylightSavingTime ();
-
- //FIXME: do not rely on DateTime implementation !
- if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Utc)
- return IsDaylightSavingTime (DateTime.SpecifyKind (dateTime.ToUniversalTime (), DateTimeKind.Utc));
-
- AdjustmentRule rule = GetApplicableRule (dateTime.Date);
- if (rule == null)
- return false;
- // Check whether we're in the dateTime year's DST period
- if (IsInDSTForYear (rule, dateTime, dateTime.Year))
- return true;
+ bool isDst;
+ GetUtcOffset (dateTime, out isDst);
- // We might be in the dateTime previous year's DST period
- return IsInDSTForYear (rule, dateTime, dateTime.Year - 1);
+ return isDst;
}
public bool IsDaylightSavingTime (DateTimeOffset dateTimeOffset)
return null;
}
+ private bool TryGetTransitionOffset (DateTime dateTime, out TimeSpan offset,out bool isDst)
+ {
+ offset = BaseUtcOffset;
+ isDst = false;
+
+ if (transitions == null)
+ return false;
+
+ //Transitions are always in standard time
+ DateTime date = dateTime;
+
+ if (dateTime.Kind == DateTimeKind.Local && this != TimeZoneInfo.Local)
+ date = date.ToUniversalTime () + BaseUtcOffset;
+
+ if (dateTime.Kind == DateTimeKind.Utc && this != TimeZoneInfo.Utc)
+ date = date + BaseUtcOffset;
+
+ for (var i = transitions.Count - 1; i >= 0; i--) {
+ var pair = transitions [i];
+ DateTime ttime = pair.Key;
+ TimeType ttype = pair.Value;
+
+ if (ttime > date)
+ continue;
+
+ offset = new TimeSpan (0, 0, ttype.Offset);
+ isDst = ttype.IsDst;
+
+ return true;
+ }
+
+ return false;
+ }
+
private static DateTime TransitionPoint (TransitionTime transition, int year)
{
if (transition.IsFixedDateRule)
bool dst_observed = false;
DateTime dst_start = DateTime.MinValue;
List<AdjustmentRule> adjustmentRules = new List<AdjustmentRule> ();
+ bool storeTransition = false;
for (int i = 0; i < transitions.Count; i++) {
var pair = transitions [i];
standardDisplayName = ttype.Name;
daylightDisplayName = null;
baseUtcOffset = new TimeSpan (0, 0, ttype.Offset);
+ if (adjustmentRules.Count > 0) // We ignore AdjustmentRules but store transitions.
+ storeTransition = true;
adjustmentRules = new List<AdjustmentRule> ();
dst_observed = false;
}
}
}
- if (adjustmentRules.Count == 0) {
+ TimeZoneInfo tz;
+ if (adjustmentRules.Count == 0 && !storeTransition) {
TimeType t = (TimeType)time_types [0];
if (standardDisplayName == null) {
standardDisplayName = t.Name;
baseUtcOffset = new TimeSpan (0, 0, t.Offset);
}
- return CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName);
+ tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName);
} else {
- return CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ());
+ tz = CreateCustomTimeZone (id, baseUtcOffset, id, standardDisplayName, daylightDisplayName, ValidateRules (adjustmentRules).ToArray ());
}
+
+ if (storeTransition)
+ tz.transitions = transitions;
+
+ return tz;
}
static Dictionary<int, string> ParseAbbreviations (byte [] buffer, int index, int count)
DateTime afterDST = new DateTime (2007, 10, 28, 2, 0, 0, DateTimeKind.Unspecified);
Assert.IsFalse (london.IsDaylightSavingTime (beforeDST), "Just before DST");
Assert.IsTrue (london.IsDaylightSavingTime (startDST), "the first seconds of DST");
- Assert.IsTrue (london.IsDaylightSavingTime (endDST), "The last seconds of DST");
+ Assert.IsFalse (london.IsDaylightSavingTime (endDST), "The last seconds of DST");
Assert.IsFalse (london.IsDaylightSavingTime (afterDST), "Just after DST");
}
Assert.IsTrue (london.Equals (deserialized));
}
}
+
+ [TestFixture]
+ public class MultipleDaylightSavingTimeTests {
+ private TimeZoneInfo cairo;
+ private DateTime dst1Start;
+ private DateTime dst1End;
+ private DateTime dst2Start;
+ private DateTime dst2End;
+
+ private TimeSpan baseUtcOffset;
+ private TimeSpan dstUtcOffset;
+ private TimeSpan dstOffset;
+
+ [SetUp]
+ public void CreateTimeZones ()
+ {
+ /*
+ From 1/1/2014 12:00:00 AM to 6/30/2014 12:00:00 AM
+ Delta: 01:00:00
+ Begins at 12:00 AM on 16 May
+ Ends at 1:00 AM on 29 June
+ From 7/1/2014 12:00:00 AM to 12/31/2014 12:00:00 AM
+ Delta: 01:00:00
+ Begins at 12:00 AM on 29 July
+ Ends at 12:00 AM on 26 September
+ */
+ dst1Start = new DateTime (2014, 5, 16);
+ dst1End = new DateTime (2014, 6, 29);
+ dst2Start = new DateTime (2014, 7, 29);
+ dst2End = new DateTime (2014, 9, 26);
+
+ baseUtcOffset = new TimeSpan (2, 0, 0);
+ dstUtcOffset = new TimeSpan (3, 0, 0);
+ dstOffset = dstUtcOffset - baseUtcOffset;
+
+ var rule1 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
+ new DateTime (2014, 1, 1), new DateTime (2014, 6, 30), dstOffset,
+ CreateFixedDateRule (dst1Start), CreateFixedDateRule (dst1End));
+
+ var rule2 = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule (
+ new DateTime (2014, 7, 1), new DateTime (2014, 12, 31), dstOffset,
+ CreateFixedDateRule (dst2Start), CreateFixedDateRule (dst2End));
+
+ cairo = TimeZoneInfo.CreateCustomTimeZone ("Africa/Cairo", baseUtcOffset, "Africa/Cairo", "EET", "EEST",
+ new [] {rule1, rule2});
+ }
+
+ private static TimeZoneInfo.TransitionTime CreateFixedDateRule (DateTime dateTime)
+ {
+ var time = new DateTime (dateTime.Ticks - dateTime.Date.Ticks);
+ return TimeZoneInfo.TransitionTime.CreateFixedDateRule (time, dateTime.Month, dateTime.Day);
+ }
+
+ [Test]
+ public void GetUtcOffset_FromUTC ()
+ {
+ var d = dst1Start.Add (-baseUtcOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst1End.Add (-baseUtcOffset-dstOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2Start.Add (-baseUtcOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2End.Add (-baseUtcOffset-dstOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+ }
+
+ [Test]
+ public void GetUtcOffset_FromLocal ()
+ {
+ var d = dst1Start.Add (-baseUtcOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ d = d.ToLocalTime ();
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst1End.Add (-baseUtcOffset-dstOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ d = d.ToLocalTime ();
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2Start.Add (-baseUtcOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ d = d.ToLocalTime ();
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2End.Add (-baseUtcOffset-dstOffset);
+ d = DateTime.SpecifyKind (d, DateTimeKind.Utc);
+ d = d.ToLocalTime ();
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+ }
+
+ [Test]
+ public void GetUtcOffset_FromUnspecified ()
+ {
+ var d = dst1Start.Add (dstOffset);
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst1End.Add (-dstOffset);
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2Start.Add (dstOffset);
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+
+ d = dst2End.Add (-dstOffset);
+ Assert.AreEqual(dstUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0,-1))));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d));
+ Assert.AreEqual(baseUtcOffset, cairo.GetUtcOffset (d.Add (new TimeSpan(0,0,0, 1))));
+ }
+ }
}
}
#endif
<Compile Include="Assembly\AssemblyInfo.cs" />\r
<Compile Include="System.IdentityModel\CookieTransform.cs" />\r
<Compile Include="System.IdentityModel\OpenObject.cs" />\r
+ <Compile Include="System.IdentityModel\SignatureVerificationFailedException.cs" />\r
<Compile Include="System.IdentityModel.Claims\Claim.cs" />\r
<Compile Include="System.IdentityModel.Claims\ClaimSet.cs" />\r
<Compile Include="System.IdentityModel.Claims\ClaimTypes.cs" />\r
<Compile Include="System.IdentityModel.Tokens\SecurityToken.cs" />\r
<Compile Include="System.IdentityModel.Tokens\SecurityTokenDescriptor.cs" />\r
<Compile Include="System.IdentityModel.Tokens\SecurityTokenException.cs" />\r
- <Compile Include="System.IdentityModel.Tokens\SecurityTokenHandler.cs" />\r
+ <Compile Include="System.IdentityModel.Tokens\SecurityTokenExpiredException.cs" />\r
+ <Compile Include="System.IdentityModel.Tokens\SecurityTokenHandler.cs" />\r
<Compile Include="System.IdentityModel.Tokens\SecurityTokenHandlerCollection.cs" />\r
<Compile Include="System.IdentityModel.Tokens\SecurityTokenHandlerConfiguration.cs" />\r
+ <Compile Include="System.IdentityModel.Tokens\SecurityTokenNotYetValidException.cs" />\r
+ <Compile Include="System.IdentityModel.Tokens\SecurityTokenReplayDetectedException.cs" />\r
<Compile Include="System.IdentityModel.Tokens\SecurityTokenTypes.cs" />\r
<Compile Include="System.IdentityModel.Tokens\SecurityTokenValidationException.cs" />\r
<Compile Include="System.IdentityModel.Tokens\SessionSecurityToken.cs" />\r
<Compile Include="System.IdentityModel.Tokens\X509SubjectKeyIdentifierClause.cs" />\r
<Compile Include="System.IdentityModel.Tokens\X509ThumbprintKeyIdentifierClause.cs" />\r
<Compile Include="System.IdentityModel.Tokens\X509WindowsSecurityToken.cs" />\r
- <Compile Include="System.Security.Claims\AuthenticationTypes.cs" />\r <Compile Include="System.ServiceModel.Security\X509CertificateValidationMode.cs" />\r
+ <Compile Include="System.Security.Claims\AuthenticationTypes.cs" />\r
+ <Compile Include="System.ServiceModel.Security\X509CertificateValidationMode.cs" />\r
</ItemGroup>\r
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r
Other similar extension points exist, see Microsoft.Common.targets.\r
</Target>\r
-->\r
<PropertyGroup>\r
- <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
-
- </PreBuildEvent>
- <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">
-
- </PreBuildEvent>
+ <PreBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">\r
+\r
+ </PreBuildEvent>\r
+ <PreBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
+\r
+ </PreBuildEvent>\r
+\r
+ <PostBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">\r
+\r
+ </PostBuildEvent>\r
+ <PostBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">\r
\r
- <PostBuildEvent Condition=" '$(OS)' != 'Windows_NT' ">
-
- </PostBuildEvent>
- <PostBuildEvent Condition=" '$(OS)' == 'Windows_NT' ">
-
</PostBuildEvent>\r
</PropertyGroup>\r
<ItemGroup>\r
<Folder Include="Properties\" />\r
</ItemGroup>\r
</Project>\r
-
+\r
--- /dev/null
+//
+// SecurityTokenExpiredException.cs
+//
+// Author:
+// Noesis Labs (Ryan.Melena@noesislabs.com)
+//
+// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com
+//
+// 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.
+//
+#if NET_4_5
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IdentityModel.Tokens
+{
+ public class SecurityTokenExpiredException : SecurityTokenValidationException
+ {
+ public SecurityTokenExpiredException()
+ : base("ID4181: The security token has expired.")
+ { }
+
+ public SecurityTokenExpiredException(string message)
+ : base(message)
+ { }
+
+ public SecurityTokenExpiredException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ public SecurityTokenExpiredException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+ }
+}
+#endif
--- /dev/null
+//
+// SecurityTokenNotYetValidException.cs
+//
+// Author:
+// Noesis Labs (Ryan.Melena@noesislabs.com)
+//
+// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com
+//
+// 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.
+//
+#if NET_4_5
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IdentityModel.Tokens
+{
+ public class SecurityTokenNotYetValidException : SecurityTokenValidationException
+ {
+ public SecurityTokenNotYetValidException()
+ : base("ID4182: The security token is not valid yet.")
+ { }
+
+ public SecurityTokenNotYetValidException(string message)
+ : base(message)
+ { }
+
+ public SecurityTokenNotYetValidException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ public SecurityTokenNotYetValidException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+ }
+}
+#endif
--- /dev/null
+//
+// SecurityTokenReplayDetectedException.cs
+//
+// Author:
+// Noesis Labs (Ryan.Melena@noesislabs.com)
+//
+// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com
+//
+// 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.
+//
+#if NET_4_5
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IdentityModel.Tokens
+{
+ public class SecurityTokenReplayDetectedException : SecurityTokenValidationException
+ {
+ public SecurityTokenReplayDetectedException()
+ : base("ID1070: Replay has been detected for a SecurityToken.")
+ { }
+
+ public SecurityTokenReplayDetectedException(string message)
+ : base(message)
+ { }
+
+ public SecurityTokenReplayDetectedException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ public SecurityTokenReplayDetectedException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+ }
+}
+#endif
Assembly/AssemblyInfo.cs
System.IdentityModel/CookieTransform.cs
System.IdentityModel/OpenObject.cs
+System.IdentityModel/SignatureVerificationFailedException.cs
System.IdentityModel.Claims/Claim.cs
System.IdentityModel.Claims/ClaimSet.cs
System.IdentityModel.Claims/ClaimTypes.cs
System.IdentityModel.Tokens/SecurityToken.cs
System.IdentityModel.Tokens/SecurityTokenDescriptor.cs
System.IdentityModel.Tokens/SecurityTokenException.cs
+System.IdentityModel.Tokens/SecurityTokenExpiredException.cs
System.IdentityModel.Tokens/SecurityTokenHandler.cs
System.IdentityModel.Tokens/SecurityTokenHandlerCollection.cs
System.IdentityModel.Tokens/SecurityTokenHandlerConfiguration.cs
+System.IdentityModel.Tokens/SecurityTokenNotYetValidException.cs
+System.IdentityModel.Tokens/SecurityTokenReplayDetectedException.cs
System.IdentityModel.Tokens/SecurityTokenTypes.cs
System.IdentityModel.Tokens/SecurityTokenValidationException.cs
System.IdentityModel.Tokens/SessionSecurityToken.cs
System.IdentityModel.Tokens/X509ThumbprintKeyIdentifierClause.cs
System.IdentityModel.Tokens/X509WindowsSecurityToken.cs
System.Security.Claims/AuthenticationTypes.cs
-System.ServiceModel.Security/X509CertificateValidationMode.cs
\ No newline at end of file
+System.ServiceModel.Security/X509CertificateValidationMode.cs
--- /dev/null
+//
+// SignatureVerificationFailedException.cs
+//
+// Author:
+// Noesis Labs (Ryan.Melena@noesislabs.com)
+//
+// Copyright (C) 2014 Noesis Labs, LLC https://noesislabs.com
+//
+// 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.
+//
+#if NET_4_5
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IdentityModel
+{
+ public class SignatureVerificationFailedException : Exception
+ {
+ public SignatureVerificationFailedException()
+ : base("ID4038: Signature verification failed.")
+ { }
+
+ public SignatureVerificationFailedException(string message)
+ : base(message)
+ { }
+
+ public SignatureVerificationFailedException(string message, Exception innerException)
+ : base(message, innerException)
+ { }
+
+ public SignatureVerificationFailedException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ { }
+ }
+}
+#endif
return w.GetSection (sectionName);
}
- [MonoTODO]
public override object GetService (Type serviceType)
{
- throw new NotImplementedException ();
+ return ((IServiceProvider)w).GetService (serviceType);
}
#if NET_4_0
public override void RemapHandler (IHttpHandler handler)
#if NET_4_5
public virtual ReadEntityBodyMode ReadEntityBodyMode { get { NotImplemented(); return ReadEntityBodyMode.Classic; } }
+
+ public virtual UnvalidatedRequestValuesBase Unvalidated { get { NotImplemented (); return null; } }
#endif
+
public virtual Uri Url { get { NotImplemented (); return null; } }
public virtual Uri UrlReferrer { get { NotImplemented (); return null; } }
get { return w.TotalBytes; }
}
+#if NET_4_5
+ public override UnvalidatedRequestValuesBase Unvalidated {
+ get { return new UnvalidatedRequestValuesWrapper (w.Unvalidated); }
+ }
+#endif
+
+#if NET_4_5
+ public override ReadEntityBodyMode ReadEntityBodyMode {
+ get { return ReadEntityBodyMode.Classic; }
+ }
+#endif
+
public override Uri Url {
get { return w.Url; }
}
using System.Security.Principal;
using System.Text;
using System.Web.Caching;
+using System.Threading;
#if NET_4_0
using System.Web.Routing;
public virtual string Charset { get { NotImplemented (); return null; } set { NotImplemented (); } }
+#if NET_4_5
+ public virtual CancellationToken ClientDisconnectedToken { get { NotImplemented (); return CancellationToken.None; } }
+#endif
+
public virtual Encoding ContentEncoding { get { NotImplemented (); return null; } set { NotImplemented (); } }
public virtual string ContentType { get { NotImplemented (); return null; } set { NotImplemented (); } }
public virtual bool SuppressContent { get { NotImplemented (); return false; } set { NotImplemented (); } }
+#if NET_4_5
+ public virtual bool SuppressFormsAuthenticationRedirect { get { NotImplemented (); return false; } set { NotImplemented (); } }
+#endif
+
public virtual bool TrySkipIisCustomErrors { get { NotImplemented (); return false; } set { NotImplemented (); } }
using System.Security.Principal;
using System.Text;
using System.Web.Caching;
+using System.Threading;
namespace System.Web
{
set { w.Charset = value; }
}
+#if NET_4_5
+ public override CancellationToken ClientDisconnectedToken {
+ get { return CancellationToken.None; }
+ }
+#endif
+
public override Encoding ContentEncoding {
get { return w.ContentEncoding; }
set { w.ContentEncoding = value; }
set { w.SuppressContent = value; }
}
+#if NET_4_5
+ public override bool SuppressFormsAuthenticationRedirect {
+ get { return w.SuppressFormsAuthenticationRedirect; }
+ set { w.SuppressFormsAuthenticationRedirect = value; }
+ }
+#endif
+
public override bool TrySkipIisCustomErrors {
get { return w.TrySkipIisCustomErrors; }
set { w.TrySkipIisCustomErrors = value; }
}
public object Deserialize (string input, Type targetType) {
- return DeserializeObjectInternal (input);
+ object obj = DeserializeObjectInternal (input);
+
+ if (obj == null) return null;
+
+ return ConvertToType (obj, targetType);
}
static object Evaluate (object value) {
//object oo = ser.DeserializeObject ("{value:'Purple\\r \\n monkey\\'s:\\tdishwasher'}");
}
+ [Test]
+ public void TestDeserializeNonGenericOverload()
+ {
+ JavaScriptSerializer ser = new JavaScriptSerializer();
+ Assert.IsNull(ser.Deserialize("", typeof(X)));
+
+ X s = new X();
+ s.Init();
+ string x = ser.Serialize(s);
+
+ Assert.AreEqual("{\"z\":8,\"ch\":\"v\",\"ch_null\":null,\"str\":\"vwF59g\",\"b\":253,\"sb\":-48,\"sh\":-32740,\"ush\":65511,\"i\":-234235453,\"ui\":4294733061,\"l\":-9223372036854775780,\"ul\":18446744073709551612,\"f\":NaN,\"f1\":-Infinity,\"f2\":Infinity,\"f3\":-3.40282347E+38,\"f4\":3.40282347E+38,\"d\":NaN,\"d1\":-Infinity,\"d2\":Infinity,\"d3\":-1.7976931348623157E+308,\"d4\":1.7976931348623157E+308,\"de\":-1,\"de1\":0,\"de2\":1,\"de3\":-79228162514264337593543950335,\"de4\":79228162514264337593543950335,\"g\":\"000000ea-0002-0162-0102-030405060708\",\"nb\":null,\"dbn\":null,\"uri\":\"http://kostat@mainsoft/adfasdf/asdfasdf.aspx/asda/ads?a=b&c=d\",\"hash\":{\"mykey\":{\"BB\":10}},\"point\":{\"IsEmpty\":false,\"X\":150,\"Y\":150},\"MyEnum\":[1,10,345],\"MyEnum1\":[1,10,345],\"AA\":5,\"AA1\":[{\"BB\":10},{\"BB\":10}],\"BB\":18446744073709551610,\"YY\":[{\"BB\":10},{\"BB\":10}]}", x, "#A1");
+
+ X n = ser.Deserialize(x, typeof(X)) as X;
+ Assert.AreEqual(s, n, "#A2");
+ }
+
[Test]
public void TestDeserializeTypeResolver ()
{
<Compile Include="System.Web\DefaultExceptionPageTemplate.cs" />\r
<Compile Include="System.Web\DefaultHttpHandler.cs" />\r
<Compile Include="System.Web\EndEventHandler.cs" />\r
+ <Compile Include="System.Web\EventHandlerTaskAsyncHelper.cs" />\r
<Compile Include="System.Web\ExceptionPageTemplate.cs" />\r
<Compile Include="System.Web\ExceptionPageTemplateFragment.cs" />\r
<Compile Include="System.Web\ExceptionPageTemplateFragmentValue.cs" />\r
<Compile Include="System.Web\HttpRuntime.cs" />\r
<Compile Include="System.Web\HttpServerUtility.cs" />\r
<Compile Include="System.Web\HttpStaticObjectsCollection.cs" />\r
+ <Compile Include="System.Web\HttpTaskAsyncHandler.cs" />\r
<Compile Include="System.Web\HttpUnhandledException.cs" />\r
<Compile Include="System.Web\HttpUtility.cs" />\r
<Compile Include="System.Web\HttpValidationStatus.cs" />\r
<Compile Include="System.Web\SiteMapResolveEventArgs.cs" />\r
<Compile Include="System.Web\StaticFileHandler.cs" />\r
<Compile Include="System.Web\StaticSiteMapProvider.cs" />\r
+ <Compile Include="System.Web\TaskAsyncResult.cs" />\r
+ <Compile Include="System.Web\TaskEventHandler.cs" />\r
<Compile Include="System.Web\TempFileStream.cs" />\r
<Compile Include="System.Web\TraceContext.cs" />\r
<Compile Include="System.Web\TraceContextEventArgs.cs" />\r
<Compile Include="System.Web\DefaultExceptionPageTemplate.cs" />\r
<Compile Include="System.Web\DefaultHttpHandler.cs" />\r
<Compile Include="System.Web\EndEventHandler.cs" />\r
+ <Compile Include="System.Web\EventHandlerTaskAsyncHelper.cs" />\r
<Compile Include="System.Web\ExceptionPageTemplate.cs" />\r
<Compile Include="System.Web\ExceptionPageTemplateFragment.cs" />\r
<Compile Include="System.Web\ExceptionPageTemplateFragmentValue.cs" />\r
<Compile Include="System.Web\HttpRuntime.cs" />\r
<Compile Include="System.Web\HttpServerUtility.cs" />\r
<Compile Include="System.Web\HttpStaticObjectsCollection.cs" />\r
+ <Compile Include="System.Web\HttpTaskAsyncHandler.cs" />\r
<Compile Include="System.Web\HttpUnhandledException.cs" />\r
<Compile Include="System.Web\HttpUtility.cs" />\r
<Compile Include="System.Web\HttpValidationStatus.cs" />\r
<Compile Include="System.Web\ProcessShutdownReason.cs" />\r
<Compile Include="System.Web\ProcessStatus.cs" />\r
<Compile Include="System.Web\QueueManager.cs" />\r
+ <Compile Include="System.Web\ReadEntityBodyMode.cs" />\r
<Compile Include="System.Web\RequestNotification.cs" />\r
<Compile Include="System.Web\RequestNotificationStatus.cs" />\r
<Compile Include="System.Web\ServerVariablesCollection.cs" />\r
<Compile Include="System.Web\SiteMapResolveEventArgs.cs" />\r
<Compile Include="System.Web\StaticFileHandler.cs" />\r
<Compile Include="System.Web\StaticSiteMapProvider.cs" />\r
+ <Compile Include="System.Web\TaskAsyncResult.cs" />\r
+ <Compile Include="System.Web\TaskEventHandler.cs" />\r
<Compile Include="System.Web\TempFileStream.cs" />\r
<Compile Include="System.Web\TraceContext.cs" />\r
<Compile Include="System.Web\TraceContextEventArgs.cs" />\r
<Compile Include="Test\System.Web.Util\UrlUtilsTest.cs" />\r
<Compile Include="Test\System.Web.Util\WorkItemCas.cs" />\r
<Compile Include="Test\System.Web\AppBrowsersTest.cs" />\r
+ <Compile Include="Test\System.Web\EventHandlerTaskAsyncHelperTest.cs" />\r
<Compile Include="Test\System.Web\HttpApplicationCas.cs" />\r
<Compile Include="Test\System.Web\HttpApplicationStateCas.cs" />\r
<Compile Include="Test\System.Web\HttpApplicationTest.cs" />\r
<Compile Include="Test\System.Web\HttpServerUtilityCas.cs" />\r
<Compile Include="Test\System.Web\HttpServerUtilityTest.cs" />\r
<Compile Include="Test\System.Web\HttpStaticObjectsCollectionCas.cs" />\r
+ <Compile Include="Test\System.Web\HttpTaskAsyncHandlerTest.cs" />\r
<Compile Include="Test\System.Web\HttpUnhandledExceptionCas.cs" />\r
<Compile Include="Test\System.Web\HttpUtilityCas.cs" />\r
<Compile Include="Test\System.Web\HttpUtilityTest.cs" />\r
<Compile Include="Test\System.Web\SiteMapNodeTest.cs" />\r
<Compile Include="Test\System.Web\SiteMapProviderTest.cs" />\r
<Compile Include="Test\System.Web\StaticSiteMapProviderTest.cs" />\r
+ <Compile Include="Test\System.Web\TaskAsyncResultTest.cs" />\r
<Compile Include="Test\System.Web\TraceContextCas.cs" />\r
<Compile Include="Test\System.Web\TraceContextRecordTest.cs" />\r
<Compile Include="Test\System.Web\VirtualPathUtilityTest.cs" />\r
if (context.Response.StatusCode != 401 || context.Request.QueryString ["ReturnUrl"] != null)
return;
+#if NET_4_5
+ if (context.Response.StatusCode == 401 && context.Response.SuppressFormsAuthenticationRedirect)
+ return;
+#endif
+
string loginPage;
InitConfig (context);
#if NET_2_0
--- /dev/null
+//
+// System.Web.EventHandlerTaskAsyncHelper.cs
+//
+// Author:
+// Kornel Pal (kornelpal@gmail.com)
+//
+// Copyright (C) 2014 Kornel Pal
+//
+// 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.Threading.Tasks;
+
+namespace System.Web
+{
+ public sealed class EventHandlerTaskAsyncHelper
+ {
+ readonly TaskEventHandler taskEventHandler;
+ readonly BeginEventHandler beginEventHandler;
+ static readonly EndEventHandler endEventHandler = TaskAsyncResult.Wait;
+
+ public BeginEventHandler BeginEventHandler {
+ get { return beginEventHandler; }
+ }
+
+ public EndEventHandler EndEventHandler {
+ get { return endEventHandler; }
+ }
+
+ public EventHandlerTaskAsyncHelper (TaskEventHandler handler)
+ {
+ if (handler == null)
+ throw new ArgumentNullException ("handler");
+
+ taskEventHandler = handler;
+ beginEventHandler = GetAsyncResult;
+ }
+
+ IAsyncResult GetAsyncResult (object sender, EventArgs e, AsyncCallback callback, object state)
+ {
+ Task task = taskEventHandler (sender, e);
+ return TaskAsyncResult.GetAsyncResult (task, callback, state);
+ }
+ }
+}
string unescaped_path;
string original_path;
string path_info;
+ string path_info_unvalidated;
string raw_url;
+ string raw_url_unvalidated;
WebROCollection all_params;
- WebROCollection headers;
+ NameValueCollection headers;
+ WebROCollection headers_unvalidated;
Stream input_stream;
InputFilterStream input_filter;
Stream filter;
HttpCookieCollection cookies;
+ HttpCookieCollection cookies_unvalidated;
string http_method;
WebROCollection form;
}
}
- public HttpCookieCollection Cookies {
+ internal HttpCookieCollection CookiesNoValidation {
get {
- if (cookies == null) {
+ if (cookies_unvalidated == null) {
if (worker_request == null) {
- cookies = new HttpCookieCollection ();
+ cookies_unvalidated = new HttpCookieCollection ();
} else {
string cookie_hv = worker_request.GetKnownRequestHeader (HttpWorkerRequest.HeaderCookie);
- cookies = new HttpCookieCollection (cookie_hv);
+ cookies_unvalidated = new HttpCookieCollection (cookie_hv);
}
}
+ return cookies_unvalidated;
+ }
+ }
+
+ public HttpCookieCollection Cookies {
+ get {
+ if (cookies == null) {
+ cookies = CookiesNoValidation;
+ }
+
#if TARGET_J2EE
// For J2EE portal support we emulate cookies using the session.
GetSessionCookiesForPortal (cookies);
}
}
+ internal NameValueCollection HeadersNoValidation {
+ get {
+ if (headers_unvalidated == null) {
+ headers_unvalidated = new HeadersCollection (this);
+ }
+
+ return headers_unvalidated;
+ }
+ }
+
public NameValueCollection Headers {
get {
if (headers == null) {
- headers = new HeadersCollection (this);
+ headers = HeadersNoValidation;
#if NET_4_0
if (validateRequestNewMode) {
RequestValidator validator = RequestValidator.Current;
}
}
+ internal string PathInfoNoValidation {
+ get {
+ if (path_info_unvalidated == null) {
+ if (worker_request == null)
+ return String.Empty;
+
+ path_info_unvalidated = worker_request.GetPathInfo () ?? String.Empty;
+ }
+
+ return path_info_unvalidated;
+ }
+ }
+
public string PathInfo {
get {
if (path_info == null) {
- if (worker_request == null)
- return String.Empty;
- path_info = worker_request.GetPathInfo () ?? String.Empty;
+ path_info = PathInfoNoValidation;
#if NET_4_0
if (validateRequestNewMode) {
RequestValidator validator = RequestValidator.Current;
}
}
- public string RawUrl {
+ internal string RawUrlUnvalidated {
get {
- if (raw_url == null) {
+ if (raw_url_unvalidated == null) {
if (worker_request != null)
- raw_url = worker_request.GetRawUrl ();
+ raw_url_unvalidated = worker_request.GetRawUrl ();
else
- raw_url = UrlComponents.Path + UrlComponents.Query;
+ raw_url_unvalidated = UrlComponents.Path + UrlComponents.Query;
- if (raw_url == null)
- raw_url = String.Empty;
+ if (raw_url_unvalidated == null)
+ raw_url_unvalidated = String.Empty;
+ }
+
+ return raw_url_unvalidated;
+ }
+ }
+
+ public string RawUrl {
+ get {
+ if (raw_url == null) {
+ raw_url = RawUrlUnvalidated;
#if NET_4_0
if (validateRequestNewMode) {
RequestValidator validator = RequestValidator.Current;
}
}
+#if NET_4_5
+ public UnvalidatedRequestValues Unvalidated {
+ get {
+ var vals = new UnvalidatedRequestValues ();
+
+ vals.Cookies = CookiesNoValidation;
+ vals.Files = Files;
+ vals.Form = FormUnvalidated;
+ vals.Headers = HeadersNoValidation;
+ vals.Path = PathNoValidation;
+ vals.PathInfo = PathInfoNoValidation;
+ vals.QueryString = QueryStringUnvalidated;
+ vals.RawUrl = RawUrlUnvalidated;
+ vals.Url = Url;
+
+ return vals;
+ }
+ }
+#endif
+
public Uri Url {
get {
if (cached_url == null) {
set;
}
+#if NET_4_5
+ public bool SuppressFormsAuthenticationRedirect {
+ get;
+ set;
+ }
+#endif
+
public bool TrySkipIisCustomErrors {
get;
set;
--- /dev/null
+//
+// System.Web.HttpTaskAsyncHandler.cs
+//
+// Author:
+// Kornel Pal (kornelpal@gmail.com)
+//
+// Copyright (C) 2014 Kornel Pal
+//
+// 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.ComponentModel;
+using System.Threading.Tasks;
+
+namespace System.Web
+{
+ public abstract class HttpTaskAsyncHandler : IHttpAsyncHandler, IHttpHandler
+ {
+ public virtual bool IsReusable {
+ get { return false; }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public virtual void ProcessRequest (HttpContext context)
+ {
+ throw new NotSupportedException ("This handler cannot be executed synchronously.");
+ }
+
+ public abstract Task ProcessRequestAsync (HttpContext context);
+
+ IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
+ {
+ Task task = ProcessRequestAsync (context);
+ return TaskAsyncResult.GetAsyncResult (task, cb, extraData);
+ }
+
+ void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
+ {
+ TaskAsyncResult.Wait (result);
+ }
+ }
+}
--- /dev/null
+//
+// System.Web.TaskAsyncResult.cs
+//
+// Author:
+// Kornel Pal (kornelpal@gmail.com)
+//
+// Copyright (C) 2014 Kornel Pal
+//
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace System.Web
+{
+ sealed class TaskAsyncResult : IAsyncResult
+ {
+ static readonly Action<Task, object> invokeCallback = InvokeCallback;
+ readonly Task task;
+ readonly AsyncCallback callback;
+
+ public object AsyncState {
+ get;
+ private set;
+ }
+
+ public WaitHandle AsyncWaitHandle {
+ get { return ((IAsyncResult) task).AsyncWaitHandle; }
+ }
+
+ public bool CompletedSynchronously {
+ get;
+ private set;
+ }
+
+ public bool IsCompleted {
+ get { return task.IsCompleted; }
+ }
+
+ TaskAsyncResult (Task task, AsyncCallback callback, object state)
+ {
+ this.task = task;
+ this.callback = callback;
+ this.AsyncState = state;
+ this.CompletedSynchronously = task.IsCompleted;
+ }
+
+ public static IAsyncResult GetAsyncResult (Task task, AsyncCallback callback, object state)
+ {
+ if (task == null)
+ return null;
+
+ var result = new TaskAsyncResult (task, callback, state);
+
+ if (callback != null) {
+ if (result.CompletedSynchronously)
+ callback (result);
+ else
+ task.ContinueWith (invokeCallback, result);
+ }
+
+ return result;
+ }
+
+ public static void Wait (IAsyncResult result)
+ {
+ if (result == null)
+ throw new ArgumentNullException ("result");
+
+ var taskAsyncResult = result as TaskAsyncResult;
+ if (taskAsyncResult == null)
+ throw new ArgumentException ("The provided IAsyncResult is invalid.", "result");
+
+ taskAsyncResult.task.GetAwaiter ().GetResult ();
+ }
+
+ static void InvokeCallback (Task task, object state)
+ {
+ var result = (TaskAsyncResult) state;
+ result.callback (result);
+ }
+ }
+}
--- /dev/null
+//
+// System.Web.TaskEventHandler.cs
+//
+// Author:
+// Kornel Pal (kornelpal@gmail.com)
+//
+// Copyright (C) 2014 Kornel Pal
+//
+// 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.Threading.Tasks;
+
+namespace System.Web
+{
+ public delegate Task TaskEventHandler (object sender, EventArgs e);
+}
--- /dev/null
+//
+// System.Web.UnvalidatedRequestValues.cs
+//
+// Author:
+// Mike Morano <mmorano@mikeandwan.us>
+//
+
+//
+// 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.Specialized;
+
+
+namespace System.Web {
+ public sealed class UnvalidatedRequestValues {
+ public HttpCookieCollection Cookies { get; internal set; }
+ public HttpFileCollection Files { get; internal set; }
+ public NameValueCollection Form { get; internal set; }
+ public NameValueCollection Headers { get; internal set; }
+ public string Path { get; internal set; }
+ public string PathInfo { get; internal set; }
+ public NameValueCollection QueryString { get; internal set; }
+ public string RawUrl { get; internal set; }
+ public Uri Url { get; internal set; }
+
+ public string this[string field] {
+ get {
+ if (Form != null && Form [field] != null) {
+ return Form [field];
+ }
+
+ if (Cookies != null && Cookies [field] != null) {
+ return Cookies [field].Value;
+ }
+
+ if (QueryString != null && QueryString [field] != null) {
+ return QueryString [field];
+ }
+
+ // msdn docs also suggest the ServerVariables are inspected by this indexer,
+ // but that seems odd given what is available in this class
+
+ return null;
+ }
+ }
+ }
+}
--- /dev/null
+//
+// System.Web.UnvalidatedRequestValuesBase.cs
+//
+// Author:
+// Mike Morano <mmorano@mikeandwan.us>
+//
+
+//
+// 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.Specialized;
+
+
+namespace System.Web {
+ public abstract class UnvalidatedRequestValuesBase {
+ void NotImplemented ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public virtual HttpCookieCollection Cookies
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual HttpFileCollection Files
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual NameValueCollection Form
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual NameValueCollection Headers
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual string this[string field]
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual string Path
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual string PathInfo
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual NameValueCollection QueryString
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual string RawUrl
+ {
+ get { NotImplemented (); return null; }
+ }
+
+ public virtual Uri Url
+ {
+ get { NotImplemented (); return null; }
+ }
+ }
+}
--- /dev/null
+//
+// System.Web.UnvalidatedRequestValuesWrapper.cs
+//
+// Author:
+// Mike Morano <mmorano@mikeandwan.us>
+//
+
+//
+// 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.Specialized;
+
+
+namespace System.Web {
+ public class UnvalidatedRequestValuesWrapper : UnvalidatedRequestValuesBase {
+ UnvalidatedRequestValues rv;
+
+ public UnvalidatedRequestValuesWrapper (UnvalidatedRequestValues requestValues)
+ {
+ rv = requestValues;
+ }
+
+ public override HttpCookieCollection Cookies
+ {
+ get { return rv.Cookies; }
+ }
+
+ public override HttpFileCollection Files
+ {
+ get { return rv.Files; }
+ }
+
+ public override NameValueCollection Form
+ {
+ get { return rv.Form; }
+ }
+
+ public override NameValueCollection Headers
+ {
+ get { return rv.Headers; }
+ }
+
+ public override string this[string field]
+ {
+ get { return rv[field]; }
+ }
+
+ public override string Path
+ {
+ get { return rv.Path; }
+ }
+
+ public override string PathInfo
+ {
+ get { return rv.PathInfo; }
+ }
+
+ public override NameValueCollection QueryString
+ {
+ get { return rv.QueryString; }
+ }
+
+ public override string RawUrl
+ {
+ get { return rv.RawUrl; }
+ }
+
+ public override Uri Url
+ {
+ get { return rv.Url; }
+ }
+ }
+}
mainsoft/NunitWeb/NunitWeb/Tests/Book.cs
mainsoft/NunitWeb/NunitWeb/Tests/BookType.cs
System.Web/AppBrowsersTest.cs
+System.Web/EventHandlerTaskAsyncHelperTest.cs
System.Web/HttpApplicationTest.cs
System.Web/HttpBrowserCapabilitiesTest.cs
System.Web/HttpCacheVaryByContentEncodingsTest.cs
System.Web/HttpResponseTest.cs
System.Web/HttpRuntimeTest.cs
System.Web/HttpServerUtilityTest.cs
+System.Web/HttpTaskAsyncHandlerTest.cs
System.Web/HttpUtilityTest.cs
System.Web/SiteMapProviderTest.cs
System.Web/SiteMapNodeTest.cs
System.Web/StaticSiteMapProviderTest.cs
+System.Web/TaskAsyncResultTest.cs
System.Web/TraceContextRecordTest.cs
System.Web.Compilation/BuildManagerTest.cs
System.Web.Compilation/ClientBuildManagerParameterTest.cs
--- /dev/null
+//
+// MonoTests.System.Web.EventHandlerTaskAsyncHelperTest.cs
+//
+// Author:
+// Kornel Pal (kornelpal@gmail.com)
+//
+// Copyright (C) 2014 Kornel Pal
+//
+// 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.
+//
+
+#if NET_4_5
+
+using System;
+using System.Threading.Tasks;
+using System.Web;
+using NUnit.Framework;
+
+namespace MonoTests.System.Web
+{
+ [TestFixture]
+ public sealed class EventHandlerTaskAsyncHelperTest : TaskAsyncResultTest
+ {
+ EventHandlerTaskAsyncHelper helper;
+ object expectedSender;
+ EventArgs expectedEventArgs;
+
+ static Task DummyTaskEventHandler (object sender, EventArgs e)
+ {
+ throw new AssertionException ("Should not be called.");
+ }
+
+ protected override void SetNullArguments ()
+ {
+ expectedSender = null;
+ expectedEventArgs = null;
+ }
+
+ protected override IAsyncResult GetAsyncResult (Func<Task> taskFactory, AsyncCallback callback, object state)
+ {
+ Assert.IsNull (helper, "GetAsyncResult#A01");
+
+ TaskEventHandler handler = (sender, e) => {
+ Assert.AreSame (expectedSender, sender, "GetAsyncResult#A02");
+ Assert.AreSame (expectedEventArgs, e, "GetAsyncResult#A03");
+
+ return taskFactory ();
+ };
+
+ helper = new EventHandlerTaskAsyncHelper (handler);
+ return helper.BeginEventHandler (expectedSender, expectedEventArgs, callback, state);
+ }
+
+ protected override void Wait (IAsyncResult result)
+ {
+ Assert.IsNotNull (helper, "Wait#A01");
+
+ helper.EndEventHandler (result);
+ }
+
+ protected override void TestSetUp ()
+ {
+ base.TestSetUp ();
+
+ helper = null;
+ expectedSender = new object ();
+ expectedEventArgs = new EventArgs ();
+ }
+
+ [Test]
+ public void Constructor ()
+ {
+ var helper = new EventHandlerTaskAsyncHelper (DummyTaskEventHandler);
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentNullException))]
+ public void Constructor_NullHandler ()
+ {
+ var helper = new EventHandlerTaskAsyncHelper (null);
+ }
+
+ [Test]
+ public void BeginEventHandler ()
+ {
+ var helper = new EventHandlerTaskAsyncHelper (DummyTaskEventHandler);
+
+ Assert.IsNotNull (helper.BeginEventHandler, "#A01");
+ }
+
+ [Test]
+ public void EndEventHandler ()
+ {
+ var helper = new EventHandlerTaskAsyncHelper (DummyTaskEventHandler);
+
+ Assert.IsNotNull (helper.EndEventHandler, "#A01");
+ }
+ }
+}
+
+#endif
--- /dev/null
+//
+// MonoTests.System.Web.HttpTaskAsyncHandlerTest.cs
+//
+// Author:
+// Kornel Pal (kornelpal@gmail.com)
+//
+// Copyright (C) 2014 Kornel Pal
+//
+// 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.
+//
+
+#if NET_4_5
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using System.Web;
+using NUnit.Framework;
+
+namespace MonoTests.System.Web
+{
+ [TestFixture]
+ public sealed class HttpTaskAsyncHandlerTest : TaskAsyncResultTest
+ {
+ sealed class DummyHttpTaskAsyncHandler : HttpTaskAsyncHandler
+ {
+ public DummyHttpTaskAsyncHandler ()
+ {
+ }
+
+ public override Task ProcessRequestAsync (HttpContext context)
+ {
+ throw new AssertionException ("Should not be called.");
+ }
+ }
+
+ sealed class TestHttpTaskAsyncHandler : HttpTaskAsyncHandler
+ {
+ readonly Func<Task> taskFactory;
+ readonly HttpContext expectedContext;
+
+ public TestHttpTaskAsyncHandler (Func<Task> taskFactory, HttpContext expectedContext)
+ {
+ this.taskFactory = taskFactory;
+ this.expectedContext = expectedContext;
+ }
+
+ public override Task ProcessRequestAsync (HttpContext context)
+ {
+ Assert.AreSame (expectedContext, context, "TestHttpTaskAsyncHandler#A01");
+
+ return taskFactory ();
+ }
+ }
+
+ IHttpAsyncHandler handler;
+ HttpContext expectedContext;
+
+ protected override void SetNullArguments ()
+ {
+ expectedContext = null;
+ }
+
+ protected override IAsyncResult GetAsyncResult (Func<Task> taskFactory, AsyncCallback callback, object state)
+ {
+ Assert.IsNull (handler, "GetAsyncResult#A01");
+
+ handler = new TestHttpTaskAsyncHandler (taskFactory, expectedContext);
+ return handler.BeginProcessRequest (expectedContext, callback, state);
+ }
+
+ protected override void Wait (IAsyncResult result)
+ {
+ Assert.IsNotNull (handler, "Wait#A01");
+
+ handler.EndProcessRequest (result);
+ }
+
+ protected override void TestSetUp ()
+ {
+ base.TestSetUp ();
+
+ handler = null;
+
+ var request = new HttpRequest (string.Empty, "http://localhost/", string.Empty);
+ var response = new HttpResponse (TextWriter.Null);
+ expectedContext = new HttpContext (request, response);
+ }
+
+ [Test]
+ public void IsReusable ()
+ {
+ var handler = new DummyHttpTaskAsyncHandler ();
+ Assert.IsFalse (handler.IsReusable, "#A01");
+ }
+
+ [Test]
+ [ExpectedException (typeof (NotSupportedException))]
+ public void ProcessRequest ()
+ {
+ var handler = new DummyHttpTaskAsyncHandler ();
+ handler.ProcessRequest (expectedContext);
+ }
+
+ [Test]
+ [ExpectedException (typeof (NotSupportedException))]
+ public void ProcessRequest_NullContext ()
+ {
+ var handler = new DummyHttpTaskAsyncHandler ();
+ handler.ProcessRequest (null);
+ }
+ }
+}
+
+#endif
--- /dev/null
+//
+// MonoTests.System.Web.TaskAsyncResultTest.cs
+//
+// Author:
+// Kornel Pal (kornelpal@gmail.com)
+//
+// Copyright (C) 2014 Kornel Pal
+//
+// 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.
+//
+
+#if NET_4_5
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using NUnit.Framework;
+
+namespace MonoTests.System.Web
+{
+ public abstract class TaskAsyncResultTest
+ {
+ sealed class TestException : Exception
+ {
+ public TestException ()
+ : base ("Test exception")
+ {
+ }
+ }
+
+ sealed class DummyAsyncResult : IAsyncResult
+ {
+ public object AsyncState {
+ get { throw new AssertionException ("Should not be called."); }
+ }
+
+ public WaitHandle AsyncWaitHandle {
+ get { throw new AssertionException ("Should not be called."); }
+ }
+
+ public bool CompletedSynchronously {
+ get { throw new AssertionException ("Should not be called."); }
+ }
+
+ public bool IsCompleted {
+ get { throw new AssertionException ("Should not be called."); }
+ }
+ }
+
+ int testThreadId;
+ int factoryCount;
+ int callbackCount;
+ object expectedState;
+ Exception expectedException;
+ TaskCompletionSource<object> taskCompletion;
+ TaskCompletionSource<object> callbackCompletion;
+ IAsyncResult taskAsyncResult;
+
+ static Task NullTaskFatory ()
+ {
+ return null;
+ }
+
+ static Task CompletedTaskFatory ()
+ {
+ return Task.FromResult<object> (null);
+ }
+
+ static Task FailingTaskFatory ()
+ {
+ throw new TestException ();
+ }
+
+ void DummyCallback (IAsyncResult result)
+ {
+ Interlocked.Increment (ref callbackCount);
+
+ Assert.Fail ("Should not be called.");
+ }
+
+ void FailingCallback (IAsyncResult result)
+ {
+ Interlocked.Increment (ref callbackCount);
+
+ throw new TestException ();
+ }
+
+ protected abstract void SetNullArguments ();
+ protected abstract IAsyncResult GetAsyncResult (Func<Task> taskFactory, AsyncCallback callback, object state);
+ protected abstract void Wait (IAsyncResult result);
+
+ [SetUp]
+ protected virtual void TestSetUp ()
+ {
+ testThreadId = Thread.CurrentThread.ManagedThreadId;
+ factoryCount = 0;
+ callbackCount = 0;
+ expectedState = new object ();
+ expectedException = null;
+ taskCompletion = new TaskCompletionSource<object> ();
+ callbackCompletion = new TaskCompletionSource<object> ();
+ taskAsyncResult = null;
+ }
+
+ [Test]
+ public void Invoke_NullArguments ()
+ {
+ SetNullArguments ();
+
+ IAsyncResult result = GetAsyncResult (CompletedTaskFatory, null, null);
+ Wait (result);
+ }
+
+ [Test]
+ public void Invoke_NullTask ()
+ {
+ IAsyncResult result = GetAsyncResult (NullTaskFatory, DummyCallback, null);
+
+ Assert.AreEqual (0, callbackCount, "#A01");
+ Assert.IsNull (result, "#A02");
+ }
+
+ [Test]
+ [ExpectedException (typeof (TestException))]
+ public void Invoke_TaskFatoryException ()
+ {
+ try {
+ GetAsyncResult (FailingTaskFatory, DummyCallback, expectedState);
+ } finally {
+ Assert.AreEqual (0, callbackCount, "#A01");
+ }
+ }
+
+ [Test]
+ [ExpectedException (typeof (TestException))]
+ public void Invoke_CallbackException ()
+ {
+ try {
+ GetAsyncResult (CompletedTaskFatory, FailingCallback, expectedState);
+ } finally {
+ Assert.AreEqual (1, callbackCount, "#A01");
+ }
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentNullException))]
+ public void Invoke_NullResult ()
+ {
+ GetAsyncResult (NullTaskFatory, DummyCallback, null);
+ Wait (null);
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentException))]
+ public void Invoke_InvalidResult ()
+ {
+ GetAsyncResult (NullTaskFatory, DummyCallback, null);
+ Wait (new DummyAsyncResult ());
+ }
+
+ void SetTaskResult ()
+ {
+ if (expectedException == null)
+ taskCompletion.SetResult (null);
+ else
+ taskCompletion.SetException (expectedException);
+ }
+
+ void WaitTaskResult ()
+ {
+ if (expectedException == null) {
+ Wait (taskAsyncResult);
+ return;
+ }
+
+ try {
+ Wait (taskAsyncResult);
+
+ Assert.Fail ("Expected exception was not thrown.");
+ } catch (AssertionException) {
+ throw;
+ } catch (Exception ex) {
+ Assert.AreSame (expectedException, ex, "WaitTaskResult#A01");
+ }
+ }
+
+ [Test]
+ public void InvokeSync ()
+ {
+ InvokeSyncCore ();
+ }
+
+ [Test]
+ public void InvokeSync_Failed ()
+ {
+ expectedException = new TestException ();
+
+ InvokeSyncCore ();
+ }
+
+ void InvokeSyncCore ()
+ {
+ IAsyncResult result = GetAsyncResult (SyncTaskFatory, SyncCallback, expectedState);
+
+ Assert.IsNotNull (result, "InvokeSyncCore#A01");
+ Assert.AreSame (taskAsyncResult, result, "InvokeSyncCore#A02");
+
+ WaitTaskResult ();
+
+ Assert.AreEqual (1, factoryCount, "InvokeSyncCore#A03");
+ Assert.AreEqual (1, callbackCount, "InvokeSyncCore#A04");
+ }
+
+ Task SyncTaskFatory ()
+ {
+ Interlocked.Increment (ref factoryCount);
+
+ Assert.AreEqual (testThreadId, Thread.CurrentThread.ManagedThreadId, "SyncTaskFatory#A01");
+
+ SetTaskResult ();
+
+ return taskCompletion.Task;
+ }
+
+ void SyncCallback (IAsyncResult result)
+ {
+ Interlocked.Increment (ref callbackCount);
+
+ Assert.AreEqual (testThreadId, Thread.CurrentThread.ManagedThreadId, "SyncCallback#A01");
+
+ Assert.IsNotNull (result, "SyncCallback#A02");
+ Assert.AreSame (expectedState, result.AsyncState, "SyncCallback#A03");
+ Assert.IsTrue (result.IsCompleted, "SyncCallback#A04");
+ Assert.IsTrue (result.CompletedSynchronously, "SyncCallback#A05");
+ Assert.IsNotNull (result.AsyncWaitHandle, "SyncCallback#A06");
+ Assert.IsTrue (result.AsyncWaitHandle.WaitOne (0), "SyncCallback#A07");
+
+ taskAsyncResult = result;
+
+ Assert.AreEqual (1, factoryCount, "SyncCallback#A08");
+ Assert.AreEqual (1, callbackCount, "SyncCallback#A09");
+ }
+
+ [Test]
+ public void InvokeAsync ()
+ {
+ InvokeAsyncCore ();
+ }
+
+ [Test]
+ public void InvokeAsync_Failed ()
+ {
+ expectedException = new TestException ();
+
+ InvokeAsyncCore ();
+ }
+
+ void InvokeAsyncCore ()
+ {
+ IAsyncResult result = GetAsyncResult (AsyncTaskFatory, AsyncCallback, expectedState);
+
+ Assert.IsNotNull (result, "InvokeAsyncCore#A01");
+ Assert.AreSame (expectedState, result.AsyncState, "InvokeAsyncCore#A02");
+ Assert.IsFalse (result.IsCompleted, "InvokeAsyncCore#A03");
+ Assert.IsFalse (result.CompletedSynchronously, "InvokeAsyncCore#A04");
+ Assert.IsNotNull (result.AsyncWaitHandle, "InvokeAsyncCore#A05");
+ Assert.IsFalse (result.AsyncWaitHandle.WaitOne (0), "InvokeAsyncCore#A06");
+
+ Assert.AreEqual (1, factoryCount, "InvokeAsyncCore#A07");
+ Assert.AreEqual (0, callbackCount, "InvokeAsyncCore#A08");
+
+ taskAsyncResult = result;
+
+ SetTaskResult ();
+
+ callbackCompletion.Task.GetAwaiter ().GetResult ();
+
+ Assert.AreEqual (1, factoryCount, "InvokeAsyncCore#A09");
+ Assert.AreEqual (1, callbackCount, "InvokeAsyncCore#A10");
+ }
+
+ Task AsyncTaskFatory ()
+ {
+ Interlocked.Increment (ref factoryCount);
+
+ Assert.AreEqual (testThreadId, Thread.CurrentThread.ManagedThreadId, "AsyncTaskFatory#A01");
+
+ return taskCompletion.Task;
+ }
+
+ void AsyncCallback (IAsyncResult result)
+ {
+ try {
+ Interlocked.Increment (ref callbackCount);
+
+ Assert.AreNotEqual (testThreadId, Thread.CurrentThread.ManagedThreadId, "AsyncCallback#A01");
+
+ Assert.IsNotNull (result, "AsyncCallback#A02");
+ Assert.AreSame (expectedState, result.AsyncState, "AsyncCallback#A03");
+ Assert.IsTrue (result.IsCompleted, "AsyncCallback#A04");
+ Assert.IsFalse (result.CompletedSynchronously, "AsyncCallback#A05");
+ Assert.IsNotNull (result.AsyncWaitHandle, "AsyncCallback#A06");
+ Assert.IsTrue (result.AsyncWaitHandle.WaitOne (0), "AsyncCallback#A07");
+
+ Assert.AreSame (taskAsyncResult, result, "AsyncCallback#A08");
+
+ WaitTaskResult ();
+
+ callbackCompletion.TrySetResult (null);
+ } catch (Exception ex) {
+ callbackCompletion.TrySetException (ex);
+ }
+ }
+ }
+}
+
+#endif
#include net_4_0_System.Web.dll.sources
+System.Web/EventHandlerTaskAsyncHelper.cs
+System.Web/HttpTaskAsyncHandler.cs
System.Web/MimeMapping.cs
System.Web/ReadEntityBodyMode.cs
-
+System.Web/UnvalidatedRequestValues.cs
+System.Web/UnvalidatedRequestValuesBase.cs
+System.Web/UnvalidatedRequestValuesWrapper.cs
+System.Web/TaskAsyncResult.cs
+System.Web/TaskEventHandler.cs
[PermissionSet (SecurityAction.InheritanceDemand, Unrestricted = true)]
public virtual XmlNode ReadNode (XmlReader reader)
{
- if (PreserveWhitespace)
- return ReadNodeCore (reader);
- XmlTextReader xtr = reader as XmlTextReader;
- if (xtr != null && xtr.WhitespaceHandling ==
- WhitespaceHandling.All) {
- try {
- xtr.WhitespaceHandling = WhitespaceHandling.Significant;
- return ReadNodeCore (reader);
- } finally {
- xtr.WhitespaceHandling = WhitespaceHandling.All;
- }
- }
- else
- return ReadNodeCore (reader);
+ return ReadNodeCore (reader);
}
XmlNode ReadNodeCore (XmlReader reader)
Assert.IsFalse (reader.ReadAttributeValue(), "#4");
Assert.AreEqual (XmlNodeType.Text, reader.NodeType, "#5");
}
+
+ [Test]
+ public void Whitespaces ()
+ {
+ const string xml = "<?xml version=\"1.0\"?><test> <foo name=\"Hello\"> <value>World</value> </foo> <foo name=\"Foo\"><value>Bar</value></foo></test>";
+ var reader = new XmlTextReader (new StringReader (xml));
+ //reader.WhitespaceHandling = WhitespaceHandling.All;
+
+ reader.Read ();
+ Assert.AreEqual (XmlNodeType.XmlDeclaration, reader.NodeType, "#1a");
+ reader.Read ();
+ Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#1b");
+ Assert.AreEqual ("test", reader.Name, "#1c");
+
+ reader.Read ();
+ if (reader.NodeType == XmlNodeType.Whitespace)
+ reader.Read ();
+
+ Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#2a");
+ Assert.AreEqual ("foo", reader.Name, "#2b");
+
+ var doc = new XmlDocument ();
+ //doc.PreserveWhitespace = true;
+ doc.ReadNode (reader);
+
+ Assert.AreEqual (XmlNodeType.Whitespace, reader.NodeType, "#3");
+
+ reader.Read ();
+ if (reader.NodeType == XmlNodeType.Whitespace)
+ reader.Read ();
+
+ Assert.AreEqual (XmlNodeType.Element, reader.NodeType, "#4");
+ Assert.AreEqual ("foo", reader.Name, "#4b");
+
+ doc.ReadNode (reader);
+
+ Assert.AreEqual (XmlNodeType.EndElement, reader.NodeType, "#5");
+ }
}
}
internal SearchPattern2 Pattern {
get {
if (pattern == null) {
- pattern = new SearchPattern2 (MangledFilter);
+ if (watcher.GetType () == typeof (KeventWatcher))
+ pattern = new SearchPattern2 (MangledFilter, true); //assume we want to ignore case (OS X)
+ else
+ pattern = new SearchPattern2 (MangledFilter);
}
return pattern;
}
ErrorEvent,
RenameEvent
}
- private void RaiseEvent (Delegate ev, EventArgs arg, EventType evtype)
- {
- if (ev == null)
- return;
-
- if (synchronizingObject == null) {
- switch (evtype) {
- case EventType.RenameEvent:
- ((RenamedEventHandler)ev).BeginInvoke (this, (RenamedEventArgs) arg, null, null);
- break;
- case EventType.ErrorEvent:
- ((ErrorEventHandler)ev).BeginInvoke (this, (ErrorEventArgs) arg, null, null);
- break;
- case EventType.FileSystemEvent:
- ((FileSystemEventHandler)ev).BeginInvoke (this, (FileSystemEventArgs) arg, null, null);
- break;
- }
- return;
- }
- synchronizingObject.BeginInvoke (ev, new object [] {this, arg});
- }
-
protected void OnChanged (FileSystemEventArgs e)
{
- RaiseEvent (Changed, e, EventType.FileSystemEvent);
+ if (Changed == null)
+ return;
+
+ if (synchronizingObject == null)
+ Changed (this, e);
+ else
+ synchronizingObject.BeginInvoke (Changed, new object[] { this, e });
}
protected void OnCreated (FileSystemEventArgs e)
{
- RaiseEvent (Created, e, EventType.FileSystemEvent);
+ if (Created == null)
+ return;
+
+ if (synchronizingObject == null)
+ Created (this, e);
+ else
+ synchronizingObject.BeginInvoke (Created, new object[] { this, e });
}
protected void OnDeleted (FileSystemEventArgs e)
{
- RaiseEvent (Deleted, e, EventType.FileSystemEvent);
+ if (Deleted == null)
+ return;
+
+ if (synchronizingObject == null)
+ Deleted (this, e);
+ else
+ synchronizingObject.BeginInvoke (Deleted, new object[] { this, e });
}
- protected void OnError (ErrorEventArgs e)
+ internal void OnError (ErrorEventArgs e)
{
- RaiseEvent (Error, e, EventType.ErrorEvent);
+ if (Error == null)
+ return;
+
+ if (synchronizingObject == null)
+ Error (this, e);
+ else
+ synchronizingObject.BeginInvoke (Error, new object[] { this, e });
}
protected void OnRenamed (RenamedEventArgs e)
{
- RaiseEvent (Renamed, e, EventType.RenameEvent);
+ if (Renamed == null)
+ return;
+
+ if (synchronizingObject == null)
+ Renamed (this, e);
+ else
+ synchronizingObject.BeginInvoke (Renamed, new object[] { this, e });
}
public WaitForChangedResult WaitForChanged (WatcherChangeTypes changeType)
//
// Authors:
// Geoff Norton (gnorton@customerdna.com)
+// Cody Russell (cody@xamarin.com)
+// Alexis Christoforides (lexas@xamarin.com)
//
// (c) 2004 Geoff Norton
// Copyright 2014 Xamarin Inc
using System;
using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
+using System.Reflection;
namespace System.IO {
VM = -11
}
+ [Flags]
enum FilterFlags : uint {
ReadPoll = EventFlags.Flag0,
ReadOutOfBand = EventFlags.Flag1,
TimerNanoSeconds = 0x00000004,
TimerAbsolute = 0x00000008,
}
-
+
+ [StructLayout(LayoutKind.Sequential)]
struct kevent : IDisposable {
- public int ident;
+ public UIntPtr ident;
public EventFilter filter;
public EventFlags flags;
public FilterFlags fflags;
- public int data;
+ public IntPtr data;
public IntPtr udata;
public void Dispose ()
if (udata != IntPtr.Zero)
Marshal.FreeHGlobal (udata);
}
+
+
}
+ [StructLayout(LayoutKind.Sequential)]
struct timespec {
- public int tv_sec;
- public int tv_usec;
+ public IntPtr tv_sec;
+ public IntPtr tv_usec;
}
- class KeventFileData {
- public FileSystemInfo fsi;
- public DateTime LastAccessTime;
- public DateTime LastWriteTime;
+ class PathData
+ {
+ public string Path;
+ public bool IsDirectory;
+ public int Fd;
+ }
- public KeventFileData(FileSystemInfo fsi, DateTime LastAccessTime, DateTime LastWriteTime) {
- this.fsi = fsi;
- this.LastAccessTime = LastAccessTime;
- this.LastWriteTime = LastWriteTime;
+ class KqueueMonitor : IDisposable
+ {
+ public int Connection
+ {
+ get { return conn; }
}
- }
- class KeventData {
- public FileSystemWatcher FSW;
- public string Directory;
- public string FileMask;
- public bool IncludeSubdirs;
- public bool Enabled;
- public Hashtable DirEntries;
- public kevent ev;
- }
+ public KqueueMonitor (FileSystemWatcher fsw)
+ {
+ this.fsw = fsw;
+ this.conn = -1;
+ }
- class KeventWatcher : IFileWatcher
- {
- static bool failed;
- static KeventWatcher instance;
- static Hashtable watches;
- static Hashtable requests;
- static Thread thread;
- static int conn;
- static bool stop;
-
- private KeventWatcher ()
+ public void Dispose ()
{
+ CleanUp ();
}
-
- // Locked by caller
- public static bool GetInstance (out IFileWatcher watcher)
+
+ public void Start ()
{
- if (failed == true) {
- watcher = null;
- return false;
- }
+ lock (stateLock) {
+ if (started)
+ return;
- if (instance != null) {
- watcher = instance;
- return true;
- }
+ conn = kqueue ();
- watches = Hashtable.Synchronized (new Hashtable ());
- requests = Hashtable.Synchronized (new Hashtable ());
- conn = kqueue();
- if (conn == -1) {
- failed = true;
- watcher = null;
- return false;
- }
+ if (conn == -1)
+ throw new IOException (String.Format (
+ "kqueue() error at init, error code = '{0}'", Marshal.GetLastWin32Error ()));
+
+ thread = new Thread (() => DoMonitor ());
+ thread.IsBackground = true;
+ thread.Start ();
- instance = new KeventWatcher ();
- watcher = instance;
- return true;
+ startedEvent.WaitOne ();
+
+ if (failedInit) {
+ thread.Join ();
+ CleanUp ();
+ throw new IOException ("Monitor thread failed while initializing.");
+ }
+ else
+ started = true;
+ }
}
-
- public void StartDispatching (FileSystemWatcher fsw)
+
+ public void Stop ()
{
- KeventData data;
- lock (this) {
- if (thread == null) {
- thread = new Thread (new ThreadStart (Monitor));
- thread.IsBackground = true;
- thread.Start ();
- }
+ lock (stateLock) {
+ if (!started)
+ return;
+
+ requestStop = true;
+ thread.Join ();
+ requestStop = false;
- data = (KeventData) watches [fsw];
+ CleanUp ();
+ started = false;
}
+ }
- if (data == null) {
- data = new KeventData ();
- data.FSW = fsw;
- data.Directory = fsw.FullPath;
- data.FileMask = fsw.MangledFilter;
- data.IncludeSubdirs = fsw.IncludeSubdirectories;
-
- data.Enabled = true;
- lock (this) {
- StartMonitoringDirectory (data);
- watches [fsw] = data;
- stop = false;
- }
- }
+ void CleanUp ()
+ {
+ if (conn != -1)
+ close (conn);
+
+ conn = -1;
+
+ foreach (int fd in fdsDict.Keys)
+ close (fd);
+
+ fdsDict.Clear ();
+ pathsDict.Clear ();
}
- static void StartMonitoringDirectory (KeventData data)
+ void DoMonitor ()
{
- DirectoryInfo dir = new DirectoryInfo (data.Directory);
- if(data.DirEntries == null) {
- data.DirEntries = new Hashtable();
- foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() )
- data.DirEntries.Add(fsi.FullName, new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime));
+ Exception exc = null;
+ failedInit = false;
+
+ try {
+ Setup ();
+ } catch (Exception e) {
+ failedInit = true;
+ exc = e;
+ } finally {
+ startedEvent.Set ();
}
- int fd = open(data.Directory, 0, 0);
- kevent ev = new kevent();
- ev.udata = IntPtr.Zero;
- timespec nullts = new timespec();
- nullts.tv_sec = 0;
- nullts.tv_usec = 0;
- if (fd > 0) {
- ev.ident = fd;
- ev.filter = EventFilter.Vnode;
- ev.flags = EventFlags.Add | EventFlags.Enable | EventFlags.OneShot;
- ev.fflags = // 20 | 2 | 1 | 8;
- FilterFlags.VNodeDelete |
- FilterFlags.VNodeWrite |
- FilterFlags.VNodeAttrib |
- // The following two values are the equivalent of the original value "20", but we suspect the original author meant
- // 0x20, we will review later with some test cases
- FilterFlags.VNodeLink |
- FilterFlags.VNodeExtend;
- ev.data = 0;
- ev.udata = Marshal.StringToHGlobalAuto (data.Directory);
- kevent outev = new kevent();
- outev.udata = IntPtr.Zero;
- kevent (conn, ref ev, 1, ref outev, 0, ref nullts);
- data.ev = ev;
- requests [fd] = data;
- }
-
- if (!data.IncludeSubdirs)
+ if (failedInit) {
+ fsw.OnError (new ErrorEventArgs (exc));
return;
+ }
+ try {
+ Monitor ();
+ } catch (Exception e) {
+ exc = e;
+ } finally {
+ if (!requestStop) { // failure
+ CleanUp ();
+ started = false;
+ }
+ if (exc != null)
+ fsw.OnError (new ErrorEventArgs (exc));
+ }
}
- public void StopDispatching (FileSystemWatcher fsw)
- {
- KeventData data;
- lock (this) {
- data = (KeventData) watches [fsw];
- if (data == null)
- return;
+ void Setup ()
+ {
+ var initialFds = new List<int> ();
- StopMonitoringDirectory (data);
- watches.Remove (fsw);
- if (watches.Count == 0)
- stop = true;
+ // GetFilenameFromFd() returns the *realpath* which can be different than fsw.FullPath because symlinks.
+ // If so, introduce a fixup step.
+ int fd = open (fsw.FullPath, O_EVTONLY, 0);
+ var resolvedFullPath = GetFilenameFromFd (fd);
+ close (fd);
- if (!data.IncludeSubdirs)
- return;
+ if (resolvedFullPath != fsw.FullPath)
+ fixupPath = resolvedFullPath;
+ else
+ fixupPath = null;
+
+ Scan (fsw.FullPath, false, ref initialFds);
+ var immediate_timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)0 };
+ var eventBuffer = new kevent[0]; // we don't want to take any events from the queue at this point
+ var changes = CreateChangeList (ref initialFds);
+
+ int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref immediate_timeout);
+
+ if (numEvents == -1) {
+ var errMsg = String.Format ("kevent() error at initial event registration, error code = '{0}'", Marshal.GetLastWin32Error ());
+ throw new IOException (errMsg);
}
}
- static void StopMonitoringDirectory (KeventData data)
+ kevent[] CreateChangeList (ref List<int> FdList)
{
- close(data.ev.ident);
+ if (FdList.Count == 0)
+ return emptyEventList;
+
+ var changes = new List<kevent> ();
+ foreach (int fd in FdList) {
+ var change = new kevent {
+
+ ident = (UIntPtr)fd,
+ filter = EventFilter.Vnode,
+ flags = EventFlags.Add | EventFlags.Enable | EventFlags.Clear,
+ fflags = FilterFlags.VNodeDelete | FilterFlags.VNodeExtend |
+ FilterFlags.VNodeRename | FilterFlags.VNodeAttrib |
+ FilterFlags.VNodeLink | FilterFlags.VNodeRevoke |
+ FilterFlags.VNodeWrite,
+ data = IntPtr.Zero,
+ udata = IntPtr.Zero
+ };
+
+ changes.Add (change);
+ }
+ FdList.Clear ();
+
+ return changes.ToArray ();
}
void Monitor ()
{
-
- while (!stop) {
- kevent ev = new kevent();
- ev.udata = IntPtr.Zero;
- kevent nullev = new kevent();
- nullev.udata = IntPtr.Zero;
- timespec ts = new timespec();
- ts.tv_sec = 0;
- ts.tv_usec = 0;
- int haveEvents;
- lock (this) {
- haveEvents = kevent (conn, ref nullev, 0, ref ev, 1, ref ts);
+ var timeout = new timespec { tv_sec = (IntPtr)0, tv_usec = (IntPtr)500000000 };
+ var eventBuffer = new kevent[32];
+ var newFds = new List<int> ();
+ List<PathData> removeQueue = new List<PathData> ();
+ List<string> rescanQueue = new List<string> ();
+
+ while (!requestStop) {
+ var changes = CreateChangeList (ref newFds);
+
+ int numEvents = kevent (conn, changes, changes.Length, eventBuffer, eventBuffer.Length, ref timeout);
+
+ if (numEvents == -1) {
+ var errMsg = String.Format ("kevent() error, error code = '{0}'", Marshal.GetLastWin32Error ());
+ fsw.OnError (new ErrorEventArgs (new IOException (errMsg)));
}
- if (haveEvents > 0) {
- // Restart monitoring
- KeventData data = (KeventData) requests [ev.ident];
- StopMonitoringDirectory (data);
- StartMonitoringDirectory (data);
- ProcessEvent (ev);
- } else {
- System.Threading.Thread.Sleep (500);
+ if (numEvents == 0)
+ continue;
+
+ for (var i = 0; i < numEvents; i++) {
+ var kevt = eventBuffer [i];
+ var pathData = fdsDict [(int)kevt.ident];
+
+ if ((kevt.flags & EventFlags.Error) == EventFlags.Error) {
+ var errMsg = String.Format ("kevent() error watching path '{0}', error code = '{1}'", pathData.Path, kevt.data);
+ fsw.OnError (new ErrorEventArgs (new IOException (errMsg)));
+ continue;
+ }
+
+ if ((kevt.fflags & FilterFlags.VNodeDelete) == FilterFlags.VNodeDelete || (kevt.fflags & FilterFlags.VNodeRevoke) == FilterFlags.VNodeRevoke)
+ removeQueue.Add (pathData);
+
+ else if ((kevt.fflags & FilterFlags.VNodeWrite) == FilterFlags.VNodeWrite) {
+ if (pathData.IsDirectory)
+ rescanQueue.Add (pathData.Path);
+ else
+ PostEvent (FileAction.Modified, pathData.Path);
+ }
+
+ else if ((kevt.fflags & FilterFlags.VNodeRename) == FilterFlags.VNodeRename) {
+ var newFilename = GetFilenameFromFd (pathData.Fd);
+
+ if (newFilename.StartsWith (fsw.FullPath))
+ Rename (pathData, newFilename);
+ else //moved outside of our watched dir so stop watching
+ RemoveTree (pathData);
+ }
+
+ else if ((kevt.fflags & FilterFlags.VNodeAttrib) == FilterFlags.VNodeAttrib || (kevt.fflags & FilterFlags.VNodeExtend) == FilterFlags.VNodeExtend)
+ PostEvent (FileAction.Modified, pathData.Path);
}
+
+ removeQueue.ForEach (Remove);
+ removeQueue.Clear ();
+
+ rescanQueue.ForEach (path => {
+ Scan (path, true, ref newFds);
+ });
+ rescanQueue.Clear ();
+ }
+ }
+
+ PathData Add (string path, bool postEvents, ref List<int> fds)
+ {
+ PathData pathData;
+ pathsDict.TryGetValue (path, out pathData);
+
+ if (pathData != null)
+ return pathData;
+
+ var fd = open (path, O_EVTONLY, 0);
+
+ if (fd == -1) {
+ fsw.OnError (new ErrorEventArgs (new IOException (String.Format (
+ "open() error while attempting to process path '{0}', error code = '{1}'", path, Marshal.GetLastWin32Error ()))));
+ return null;
}
- lock (this) {
- thread = null;
- stop = false;
+ try {
+ fds.Add (fd);
+
+ var attrs = File.GetAttributes (path);
+
+ pathData = new PathData {
+ Path = path,
+ Fd = fd,
+ IsDirectory = (attrs & FileAttributes.Directory) == FileAttributes.Directory
+ };
+
+ pathsDict.Add (path, pathData);
+ fdsDict.Add (fd, pathData);
+
+ if (postEvents)
+ PostEvent (FileAction.Added, path);
+
+ return pathData;
+ } catch (Exception e) {
+ close (fd);
+ fsw.OnError (new ErrorEventArgs (e));
+ return null;
}
+
}
- void ProcessEvent (kevent ev)
+ void Remove (PathData pathData)
{
- lock (this) {
- KeventData data = (KeventData) requests [ev.ident];
- if (!data.Enabled)
- return;
+ fdsDict.Remove (pathData.Fd);
+ pathsDict.Remove (pathData.Path);
+ close (pathData.Fd);
+ PostEvent (FileAction.Removed, pathData.Path);
+ }
- FileSystemWatcher fsw;
- string filename = "";
+ void RemoveTree (PathData pathData)
+ {
+ var toRemove = new List<PathData> ();
- fsw = data.FSW;
- FileAction fa = 0;
- DirectoryInfo dir = new DirectoryInfo (data.Directory);
- FileSystemInfo changedFsi = null;
+ toRemove.Add (pathData);
- try {
- foreach (FileSystemInfo fsi in dir.GetFileSystemInfos() )
- if (data.DirEntries.ContainsKey (fsi.FullName) && (fsi is FileInfo)) {
- KeventFileData entry = (KeventFileData) data.DirEntries [fsi.FullName];
- if (entry.LastWriteTime != fsi.LastWriteTime) {
- filename = fsi.Name;
- fa = FileAction.Modified;
- data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime);
- if (fsw.IncludeSubdirectories && fsi is DirectoryInfo) {
- data.Directory = filename;
- requests [ev.ident] = data;
- ProcessEvent(ev);
- }
- changedFsi = fsi;
- PostEvent(filename, fsw, fa, changedFsi);
- }
- }
- } catch (Exception) {
- // The file system infos were changed while we processed them
- }
- // Deleted
- try {
- bool deleteMatched = true;
- while(deleteMatched) {
- foreach (KeventFileData entry in data.DirEntries.Values) {
- if (!File.Exists (entry.fsi.FullName) && !Directory.Exists (entry.fsi.FullName)) {
- filename = entry.fsi.Name;
- fa = FileAction.Removed;
- data.DirEntries.Remove (entry.fsi.FullName);
- changedFsi = entry.fsi;
- PostEvent(filename, fsw, fa, changedFsi);
- break;
- }
- }
- deleteMatched = false;
+ if (pathData.IsDirectory) {
+ var prefix = pathData.Path + Path.DirectorySeparatorChar;
+ foreach (var path in pathsDict.Keys)
+ if (path.StartsWith (prefix)) {
+ toRemove.Add (pathsDict [path]);
}
- } catch (Exception) {
- // The file system infos were changed while we processed them
- }
- // Added
- try {
- foreach (FileSystemInfo fsi in dir.GetFileSystemInfos())
- if (!data.DirEntries.ContainsKey (fsi.FullName)) {
- changedFsi = fsi;
- filename = fsi.Name;
- fa = FileAction.Added;
- data.DirEntries [fsi.FullName] = new KeventFileData(fsi, fsi.LastAccessTime, fsi.LastWriteTime);
- PostEvent(filename, fsw, fa, changedFsi);
- }
- } catch (Exception) {
- // The file system infos were changed while we processed them
- }
-
+ }
+ toRemove.ForEach (Remove);
+ }
+ void Rename (PathData pathData, string newRoot)
+ {
+ var toRename = new List<PathData> ();
+ var oldRoot = pathData.Path;
+
+ toRename.Add (pathData);
+
+ if (pathData.IsDirectory) {
+ var prefix = oldRoot + Path.DirectorySeparatorChar;
+ foreach (var path in pathsDict.Keys)
+ if (path.StartsWith (prefix))
+ toRename.Add (pathsDict [path]);
}
+
+ toRename.ForEach ((pd) => {
+ var oldPath = pd.Path;
+ var newPath = newRoot + oldPath.Substring (oldRoot.Length);
+ pd.Path = newPath;
+ pathsDict.Remove (oldPath);
+ pathsDict.Add (newPath, pd);
+ });
+
+ PostEvent (FileAction.RenamedNewName, oldRoot, newRoot);
}
- private void PostEvent (string filename, FileSystemWatcher fsw, FileAction fa, FileSystemInfo changedFsi) {
- RenamedEventArgs renamed = null;
- if (fa == 0)
+ void Scan (string path, bool postEvents, ref List<int> fds)
+ {
+ if (requestStop)
return;
-
- if (fsw.IncludeSubdirectories && fa == FileAction.Added) {
- if (changedFsi is DirectoryInfo) {
- KeventData newdirdata = new KeventData ();
- newdirdata.FSW = fsw;
- newdirdata.Directory = changedFsi.FullName;
- newdirdata.FileMask = fsw.MangledFilter;
- newdirdata.IncludeSubdirs = fsw.IncludeSubdirectories;
-
- newdirdata.Enabled = true;
- lock (this) {
- StartMonitoringDirectory (newdirdata);
- }
+
+ var pathData = Add (path, postEvents, ref fds);
+
+ if (pathData == null)
+ return;
+
+ if (!pathData.IsDirectory)
+ return;
+
+ var dirsToProcess = new List<string> ();
+ dirsToProcess.Add (path);
+
+ while (dirsToProcess.Count > 0) {
+ var tmp = dirsToProcess [0];
+ dirsToProcess.RemoveAt (0);
+
+ var info = new DirectoryInfo (tmp);
+ FileSystemInfo[] fsInfos = null;
+ try {
+ fsInfos = info.GetFileSystemInfos ();
+
+ } catch (IOException) {
+ // this can happen if the directory has been deleted already.
+ // that's okay, just keep processing the other dirs.
+ fsInfos = new FileSystemInfo[0];
+ }
+
+ foreach (var fsi in fsInfos) {
+ if ((fsi.Attributes & FileAttributes.Directory) == FileAttributes.Directory && !fsw.IncludeSubdirectories)
+ continue;
+
+ if ((fsi.Attributes & FileAttributes.Directory) != FileAttributes.Directory && !fsw.Pattern.IsMatch (fsi.FullName))
+ continue;
+
+ var currentPathData = Add (fsi.FullName, postEvents, ref fds);
+
+ if (currentPathData != null && currentPathData.IsDirectory)
+ dirsToProcess.Add (fsi.FullName);
}
}
-
- if (!fsw.Pattern.IsMatch(filename, true))
+ }
+
+ void PostEvent (FileAction action, string path, string newPath = null)
+ {
+ RenamedEventArgs renamed = null;
+
+ if (action == 0)
return;
+ // only post events that match filter pattern. check both old and new paths for renames
+ if (!fsw.Pattern.IsMatch (path) && (newPath == null || !fsw.Pattern.IsMatch (newPath)))
+ return;
+
+ if (action == FileAction.RenamedNewName)
+ renamed = new RenamedEventArgs (WatcherChangeTypes.Renamed, "", newPath, path);
+
lock (fsw) {
- if (changedFsi.FullName.StartsWith (fsw.FullPath, StringComparison.Ordinal)) {
- if (fsw.FullPath.EndsWith ("/", StringComparison.Ordinal)) {
- filename = changedFsi.FullName.Substring (fsw.FullPath.Length);
- } else {
- filename = changedFsi.FullName.Substring (fsw.FullPath.Length + 1);
- }
- }
- fsw.DispatchEvents (fa, filename, ref renamed);
+ fsw.DispatchEvents (action, path, ref renamed);
+
if (fsw.Waiting) {
fsw.Waiting = false;
System.Threading.Monitor.PulseAll (fsw);
}
}
+ private string GetFilenameFromFd (int fd)
+ {
+ var sb = new StringBuilder (__DARWIN_MAXPATHLEN);
+
+ if (fcntl (fd, F_GETPATH, sb) != -1) {
+ if (fixupPath != null)
+ sb.Replace (fixupPath, fsw.FullPath, 0, fixupPath.Length); // see Setup()
+ return sb.ToString ();
+ } else {
+ fsw.OnError (new ErrorEventArgs (new IOException (String.Format (
+ "fcntl() error while attempting to get path for fd '{0}', error code = '{1}'", fd, Marshal.GetLastWin32Error ()))));
+ return String.Empty;
+ }
+ }
+
+ const int O_EVTONLY = 0x8000;
+ const int F_GETPATH = 50;
+ const int __DARWIN_MAXPATHLEN = 1024;
+ static readonly kevent[] emptyEventList = new System.IO.kevent[0];
+
+ FileSystemWatcher fsw;
+ int conn;
+ Thread thread;
+ volatile bool requestStop = false;
+ AutoResetEvent startedEvent = new AutoResetEvent (false);
+ bool started = false;
+ bool failedInit = false;
+ object stateLock = new object ();
+
+ readonly Dictionary<string, PathData> pathsDict = new Dictionary<string, PathData> ();
+ readonly Dictionary<int, PathData> fdsDict = new Dictionary<int, PathData> ();
+ string fixupPath = null;
+
+ [DllImport ("libc", EntryPoint="fcntl", CharSet=CharSet.Auto, SetLastError=true)]
+ static extern int fcntl (int file_names_by_descriptor, int cmd, StringBuilder sb);
+
+ [DllImport ("libc")]
+ extern static int open (string path, int flags, int mode_t);
+
[DllImport ("libc")]
- extern static int open(string path, int flags, int mode_t);
-
+ extern static int close (int fd);
+
[DllImport ("libc")]
- extern static int close(int fd);
+ extern static int kqueue ();
[DllImport ("libc")]
- extern static int kqueue();
+ extern static int kevent (int kq, [In]kevent[] ev, int nchanges, [Out]kevent[] evtlist, int nevents, [In] ref timespec time);
+ }
+
+ class KeventWatcher : IFileWatcher
+ {
+ static bool failed;
+ static KeventWatcher instance;
+ static Hashtable watches; // <FileSystemWatcher, KqueueMonitor>
+
+ private KeventWatcher ()
+ {
+ }
+
+ // Locked by caller
+ public static bool GetInstance (out IFileWatcher watcher)
+ {
+ if (failed == true) {
+ watcher = null;
+ return false;
+ }
+
+ if (instance != null) {
+ watcher = instance;
+ return true;
+ }
+
+ watches = Hashtable.Synchronized (new Hashtable ());
+ var conn = kqueue();
+ if (conn == -1) {
+ failed = true;
+ watcher = null;
+ return false;
+ }
+ close (conn);
+
+ instance = new KeventWatcher ();
+ watcher = instance;
+ return true;
+ }
+
+ public void StartDispatching (FileSystemWatcher fsw)
+ {
+ KqueueMonitor monitor;
+
+ if (watches.ContainsKey (fsw)) {
+ monitor = (KqueueMonitor)watches [fsw];
+ } else {
+ monitor = new KqueueMonitor (fsw);
+ watches.Add (fsw, monitor);
+ }
+
+ monitor.Start ();
+ }
+
+ public void StopDispatching (FileSystemWatcher fsw)
+ {
+ KqueueMonitor monitor = (KqueueMonitor)watches [fsw];
+ if (monitor == null)
+ return;
+
+ monitor.Stop ();
+ }
+
+ [DllImport ("libc")]
+ extern static int close (int fd);
[DllImport ("libc")]
- extern static int kevent(int kqueue, ref kevent ev, int nchanges, ref kevent evtlist, int nevents, ref timespec ts);
+ extern static int kqueue ();
}
}
Compile (pattern);
}
- // OSX has a retarded case-insensitive yet case-aware filesystem
+ // OSX has a case-insensitive yet case-aware filesystem
// so we need a overload in here for the Kqueue watcher
public bool IsMatch (string text, bool ignorecase)
{
bool match = String.Compare (pattern, text, ignorecase) == 0;
if (match)
return true;
-
- // This is a special case for FSW. It needs to match e.g. subdir/file.txt
- // when the pattern is "file.txt"
- int idx = text.LastIndexOf ('/');
- if (idx == -1)
- return false;
- idx++;
- if (idx == text.Length)
- return false;
-
- return (String.Compare (pattern, text.Substring (idx), ignorecase) == 0);
}
+
+ // This is a special case for FSW. It needs to match e.g. subdir/file.txt
+ // when the pattern is "file.txt"
+ var fileName = Path.GetFileName (text);
+
+ if (!hasWildcard)
+ return (String.Compare (pattern, fileName, ignorecase) == 0);
+
- return Match (ops, text, 0);
+ return Match (ops, fileName, 0);
}
public bool IsMatch (string text)
snd_pcm_hw_params_free (hw_param);
if (handle != IntPtr.Zero)
snd_pcm_close (handle);
+ sw_param = IntPtr.Zero;
+ hw_param = IntPtr.Zero;
handle = IntPtr.Zero;
}
Console.WriteLine ("failed to alloc Alsa sw param struct");
}
- if (hw_param != IntPtr.Zero)
+ if (hw_param != IntPtr.Zero) {
snd_pcm_hw_params_free (hw_param); // free hw params
- if (sw_param != IntPtr.Zero)
+ hw_param = IntPtr.Zero;
+ }
+ if (sw_param != IntPtr.Zero) {
snd_pcm_sw_params_free (sw_param); // free sw params
+ sw_param = IntPtr.Zero;
+ }
return alsa_err == 0;
}
curSocket.EndConnect (ares);
} catch (SocketException se) {
SocketError = se.SocketErrorCode;
+ } catch (ObjectDisposedException) {
+ SocketError = SocketError.OperationAborted;
} finally {
OnCompleted (this);
}
#endif
}
+#if NET_4_5
+ [MonoTODO ("Currently hardcoded to IPv4. Ideally, support v4/v6 dual-stack.")]
+ public Socket (SocketType socketType, ProtocolType protocolType)
+ : this (AddressFamily.InterNetwork, socketType, protocolType)
+ {
+ }
+#endif
+
~Socket ()
{
Dispose (false);
if (fileName == null)
throw new ArgumentNullException ("fileName");
- WebRequest request = null;
try {
SetBusy ();
cts = new CancellationTokenSource ();
- request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
- var result = await UploadFileTaskAsyncCore (request, method, fileName, cts.Token).ConfigureAwait (false);
+
+ var result = await UploadFileTaskAsyncCore (address, method, fileName, cts.Token).ConfigureAwait (false);
OnUploadFileCompleted (new UploadFileCompletedEventArgs (result, null, false, null));
return result;
} catch (WebException ex) {
OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, false, null));
throw;
} catch (OperationCanceledException) {
- if (request != null)
- request.Abort ();
OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, null, true, null));
throw;
} catch (Exception ex) {
}
}
- async Task<byte[]> UploadFileTaskAsyncCore (WebRequest request, string method,
- string fileName, CancellationToken token)
+ async Task<byte[]> UploadFileTaskAsyncCore (Uri address, string method, string fileName, CancellationToken token)
{
token.ThrowIfCancellationRequested ();
Stream reqStream = null;
Stream fStream = null;
WebResponse response = null;
+ WebRequest request = null;
fileName = Path.GetFullPath (fileName);
+ try {
+ request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
+ } catch (OperationCanceledException) {
+ }
+
try {
fStream = File.OpenRead (fileName);
token.ThrowIfCancellationRequested ();
Path.GetFileName (fileName), fileCType);
byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
ms.Write (partHeadersBytes, 0, partHeadersBytes.Length);
- await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
+ var msLength = (int)ms.Position;
+ ms.Seek (0, SeekOrigin.Begin);
+ await ms.CopyToAsync (reqStream, msLength, token).ConfigureAwait (false);
}
}
int nread;
ms.WriteByte ((byte) '-');
ms.WriteByte ((byte) '\r');
ms.WriteByte ((byte) '\n');
- await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
+ var msLength = (int)ms.Position;
+ ms.Seek (0, SeekOrigin.Begin);
+ await ms.CopyToAsync (reqStream, msLength, token).ConfigureAwait (false);
}
}
reqStream.Close ();
return state.remaining.Length > 0;
}
- if (state.elements.scheme == Uri.UriSchemeFile) {
- // under Windows all file:// URI are considered UNC, which is not the case other MacOS (e.g. Silverlight)
-#if BOOTSTRAP_BASIC
- state.elements.isUnc = (Path.DirectorySeparatorChar == '\\');
-#else
- state.elements.isUnc = Environment.IsRunningOnWindows;
-#endif
- }
-
return ParseDelimiter (state);
}
state.elements.host = state.elements.host.ToLowerInvariant ();
state.remaining = part.Substring (state.elements.host.Length);
-
+
+ if (state.elements.scheme == Uri.UriSchemeFile &&
+ state.elements.host != "") {
+ // under Windows all file://host URI are considered UNC, which is not the case other MacOS (e.g. Silverlight)
+#if BOOTSTRAP_BASIC
+ state.elements.isUnc = (Path.DirectorySeparatorChar == '\\');
+#else
+ state.elements.isUnc = Environment.IsRunningOnWindows;
+#endif
+ }
+
return state.remaining.Length > 0;
}
webClient.UploadFileAsync (uri, "PUT", tempFile);
});
}
+
+ [Test]
+ public void UploadFileAsyncContentType ()
+ {
+ var serverUri = "http://localhost:13370/";
+ var filename = Path.GetTempFileName ();
+
+ HttpListener listener = new HttpListener ();
+ listener.Prefixes.Add (serverUri);
+ listener.Start ();
+
+ using (var client = new WebClient ())
+ {
+ client.UploadFileTaskAsync (new Uri (serverUri), filename);
+ var request = listener.GetContext ().Request;
+
+ var expected = "multipart/form-data; boundary=------------";
+ Assert.AreEqual (expected.Length + 15, request.ContentType.Length);
+ Assert.AreEqual (expected, request.ContentType.Substring (0, expected.Length));
+ }
+ listener.Close ();
+ }
#endif
#if NET_4_0
Assert.AreEqual ("/%3C%3E%25%22%7B%7D%7C/%5E%60;/:@&=+$,%5B%5D%3F", uri.AbsolutePath, "Special");
}
+ [Test]
+ public void LocalFile ()
+ {
+ Uri uri = new Uri ("file:///c:/subdir/file");
+
+ Assert.AreEqual ("c:/subdir/file", uri.AbsolutePath, "AbsolutePath");
+ Assert.AreEqual ("file:///c:/subdir/file", uri.AbsoluteUri, "AbsoluteUri");
+ Assert.AreEqual ("c:\\subdir\\file", uri.LocalPath, "LocalPath");
+ Assert.AreEqual ("c:/subdir/file", uri.PathAndQuery, "PathAndQuery");
+ Assert.AreEqual (String.Empty, uri.Query, "Query");
+ Assert.AreEqual ("file", uri.Segments [3], "Segments [3]");
+
+ Assert.AreEqual (String.Empty, uri.Authority, "Authority");
+ Assert.AreEqual (String.Empty, uri.DnsSafeHost, "DnsSafeHost");
+ Assert.AreEqual (String.Empty, uri.Fragment, "Fragment");
+ Assert.AreEqual (String.Empty, uri.Host, "Host");
+ Assert.AreEqual (UriHostNameType.Basic, uri.HostNameType, "HostNameType");
+ Assert.IsTrue (uri.IsAbsoluteUri, "IsAbsoluteUri");
+ Assert.IsTrue (uri.IsDefaultPort, "IsDefaultPort");
+ Assert.IsTrue (uri.IsFile, "IsFile");
+ Assert.IsTrue (uri.IsLoopback, "IsLoopback");
+ Assert.IsFalse (uri.IsUnc, "IsUnc");
+ Assert.AreEqual ("file:///c:/subdir/file", uri.OriginalString, "OriginalString");
+ Assert.AreEqual (-1, uri.Port, "Port");
+ Assert.AreEqual ("file", uri.Scheme, "Scheme");
+ Assert.AreEqual ("/", uri.Segments [0], "Segments [0]");
+ Assert.AreEqual ("c:/", uri.Segments [1], "Segments [1]");
+ Assert.AreEqual ("subdir/", uri.Segments [2], "Segments [2]");
+ Assert.IsFalse (uri.UserEscaped, "UserEscaped");
+ Assert.AreEqual (String.Empty, uri.UserInfo, "UserInfo");
+ }
+
+ [Test]
+ public void LocalhostWinFile ()
+ {
+ Uri uri = new Uri ("file://localhost/c:/subdir/file");
+
+ Assert.AreEqual ("/c:/subdir/file", uri.AbsolutePath, "AbsolutePath");
+ Assert.AreEqual ("file://localhost/c:/subdir/file", uri.AbsoluteUri, "AbsoluteUri");
+ Assert.AreEqual (isWin32 ? "\\\\localhost\\c:\\subdir\\file" : "/c:/subdir/file", uri.LocalPath, "LocalPath");
+ Assert.AreEqual ("/c:/subdir/file", uri.PathAndQuery, "PathAndQuery");
+ Assert.AreEqual (String.Empty, uri.Query, "Query");
+ Assert.AreEqual ("file", uri.Segments [3], "Segments [3]");
+
+ Assert.AreEqual ("localhost", uri.Authority, "Authority");
+ Assert.AreEqual ("localhost", uri.DnsSafeHost, "DnsSafeHost");
+ Assert.AreEqual (String.Empty, uri.Fragment, "Fragment");
+ Assert.AreEqual ("localhost", uri.Host, "Host");
+ Assert.AreEqual (UriHostNameType.Dns, uri.HostNameType, "HostNameType");
+ Assert.IsTrue (uri.IsAbsoluteUri, "IsAbsoluteUri");
+ Assert.IsTrue (uri.IsDefaultPort, "IsDefaultPort");
+ Assert.IsTrue (uri.IsFile, "IsFile");
+ Assert.IsTrue (uri.IsLoopback, "IsLoopback");
+ Assert.AreEqual (isWin32, uri.IsUnc, "IsUnc");
+ Assert.AreEqual ("file://localhost/c:/subdir/file", uri.OriginalString, "OriginalString");
+ Assert.AreEqual (-1, uri.Port, "Port");
+ Assert.AreEqual ("file", uri.Scheme, "Scheme");
+ Assert.AreEqual ("/", uri.Segments [0], "Segments [0]");
+ Assert.AreEqual ("c:/", uri.Segments [1], "Segments [1]");
+ Assert.AreEqual ("subdir/", uri.Segments [2], "Segments [2]");
+ Assert.IsFalse (uri.UserEscaped, "UserEscaped");
+ Assert.AreEqual (String.Empty, uri.UserInfo, "UserInfo");
+ }
+
+ [Test]
+ public void LocalhostFile ()
+ {
+ Uri uri = new Uri ("file://localhost/dir/subdir/file");
+
+ Assert.AreEqual ("/dir/subdir/file", uri.AbsolutePath, "AbsolutePath");
+ Assert.AreEqual ("file://localhost/dir/subdir/file", uri.AbsoluteUri, "AbsoluteUri");
+ Assert.AreEqual (isWin32 ? "\\\\localhost\\dir\\subdir\\file" : "/dir/subdir/file", uri.LocalPath, "LocalPath");
+ Assert.AreEqual ("/dir/subdir/file", uri.PathAndQuery, "PathAndQuery");
+ Assert.AreEqual (String.Empty, uri.Query, "Query");
+ Assert.AreEqual ("file", uri.Segments [3], "Segments [3]");
+
+ Assert.AreEqual ("localhost", uri.Authority, "Authority");
+ Assert.AreEqual ("localhost", uri.DnsSafeHost, "DnsSafeHost");
+ Assert.AreEqual (String.Empty, uri.Fragment, "Fragment");
+ Assert.AreEqual ("localhost", uri.Host, "Host");
+ Assert.AreEqual (UriHostNameType.Dns, uri.HostNameType, "HostNameType");
+ Assert.IsTrue (uri.IsAbsoluteUri, "IsAbsoluteUri");
+ Assert.IsTrue (uri.IsDefaultPort, "IsDefaultPort");
+ Assert.IsTrue (uri.IsFile, "IsFile");
+ Assert.IsTrue (uri.IsLoopback, "IsLoopback");
+ Assert.AreEqual (isWin32, uri.IsUnc, "IsUnc");
+ Assert.AreEqual ("file://localhost/dir/subdir/file", uri.OriginalString, "OriginalString");
+ Assert.AreEqual (-1, uri.Port, "Port");
+ Assert.AreEqual ("file", uri.Scheme, "Scheme");
+ Assert.AreEqual ("/", uri.Segments [0], "Segments [0]");
+ Assert.AreEqual ("dir/", uri.Segments [1], "Segments [1]");
+ Assert.AreEqual ("subdir/", uri.Segments [2], "Segments [2]");
+ Assert.IsFalse (uri.UserEscaped, "UserEscaped");
+ Assert.AreEqual (String.Empty, uri.UserInfo, "UserInfo");
+ }
+
[Test]
public void PathReduction_2e ()
{
--- /dev/null
+#!/bin/sh
+
+SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+export MONO_PATH=${MONO_PATH:-$SCRIPT_PATH/../lib/net_4_5/}
+
+TZ_FAILS=0
+TZ_COUNT=0
+FORMAT="%a %b %d %T %Y"
+
+for tz in $(cd /usr/share/zoneinfo/; find * -type f -print); do
+ TZ_COUNT=$(expr $TZ_COUNT + 1)
+ SYS_DATETIME=$(date -ju -f "$FORMAT" "$(TZ=$tz date "+$FORMAT")" "+%s")
+ CS_DATETIME=$(TZ=$tz csharp -e '(int)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds;')
+ DIFF=$(expr $SYS_DATETIME - $CS_DATETIME)
+ if [ "$DIFF" -gt "5" ] || [ "$DIFF" -lt "-5" ]; then
+ TZ_FAILS=$(expr $TZ_FAILS + 1)
+ echo ""
+ echo "DateTime.Now failed with timezone: $tz"
+ echo " System: $(date -ju -f "%s" "$SYS_DATETIME" "+%Y-%m-%d %T")"
+ echo " DateTime.Now: $(date -ju -f "%s" "$CS_DATETIME" "+%Y-%m-%d %T")"
+ fi
+ echo ".\c"
+done
+echo ""
+echo "DateTime.Now failed with $TZ_FAILS of $TZ_COUNT timezones."
{
Node node = new Node ();
node.Value = item;
-
+
Node oldTail = null;
Node oldNext = null;
while (!update) {
oldTail = tail;
oldNext = oldTail.Next;
+
+ Thread.MemoryBarrier ();
// Did tail was already updated ?
if (tail == oldTail) {
Node oldHead = head;
Node oldTail = tail;
oldNext = oldHead.Next;
+
+ Thread.MemoryBarrier ();
if (oldHead == head) {
// Empty case ?
}
result = oldNext.Value;
+
+ Thread.MemoryBarrier ();
//check if head has been updated
update = head != oldHead;
--- /dev/null
+// IErrorInfo interface
+//
+// Eberhard Beilharz (eb1@sil.org)
+//
+// Copyright (C) 2011 SIL International
+using System;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace System.Runtime.InteropServices
+{
+ [ComImport]
+ [SuppressUnmanagedCodeSecurity]
+ [Guid ("1CF2B120-547D-101B-8E65-08002B2BD119")]
+ [InterfaceType (ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IErrorInfo
+ {
+ [MethodImpl (MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
+ [PreserveSig]
+ int GetGUID (out Guid pGuid);
+
+ [MethodImpl (MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
+ [PreserveSig]
+ int GetSource ([MarshalAs (UnmanagedType.BStr)] out string pBstrSource);
+
+ [MethodImpl (MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
+ [PreserveSig]
+ int GetDescription ([MarshalAs (UnmanagedType.BStr)] out string pbstrDescription);
+
+ [MethodImpl (MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
+ [PreserveSig]
+ int GetHelpFile ([MarshalAs (UnmanagedType.BStr)] out string pBstrHelpFile);
+
+ [MethodImpl (MethodImplOptions.InternalCall, MethodCodeType=MethodCodeType.Runtime)]
+ [PreserveSig]
+ int GetHelpContext (out uint pdwHelpContext);
+ }
+}
--- /dev/null
+// ManagedErrorInfo class
+//
+// Eberhard Beilharz (eb1@sil.org)
+//
+// Copyright (C) 2012 SIL International
+using System;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace System.Runtime.InteropServices
+{
+ /// <summary>
+ /// Helper class that allows to pass an exception as an IErrorInfo object. This is useful
+ /// when we get an exception in managed code that is called from unmanaged code that is called
+ /// from managed code and we want to get to the exception in the outer managed code.
+ /// </summary>
+ internal class ManagedErrorInfo: IErrorInfo
+ {
+ private Exception m_Exception;
+ public ManagedErrorInfo (Exception e)
+ {
+ m_Exception = e;
+ }
+
+ public Exception Exception {
+ get { return m_Exception; }
+ }
+
+ #region IErrorInfo
+ public int GetGUID (out Guid guid)
+ {
+ // not supported
+ guid = Guid.Empty;
+ return 0;
+ }
+
+ public int GetSource (out string source)
+ {
+ source = m_Exception.Source;
+ return 0;
+ }
+
+ public int GetDescription (out string description)
+ {
+ description = m_Exception.Message;
+ return 0;
+ }
+
+ public int GetHelpFile (out string helpFile)
+ {
+ helpFile = m_Exception.HelpLink;
+ return 0;
+ }
+
+ public int GetHelpContext(out uint helpContext)
+ {
+ // not supported
+ helpContext = 0;
+ return 0;
+ }
+ #endregion
+ }
+}
#endif // !FULL_AOT_RUNTIME
#if !FULL_AOT_RUNTIME
- [MonoTODO ("SetErrorInfo")]
public static int GetHRForException (Exception e)
{
+ var errorInfo = new ManagedErrorInfo(e);
+ SetErrorInfo (0, errorInfo);
+
return e.hresult;
}
throw new NotImplementedException ();
}
- public static Exception GetExceptionForHR (int errorCode) {
- return GetExceptionForHR (errorCode, IntPtr.Zero);
- }
-
- public static Exception GetExceptionForHR (int errorCode, IntPtr errorInfo) {
-
+ private static Exception ConvertHrToException (int errorCode)
+ {
+ const int MSEE_E_APPDOMAINUNLOADED = unchecked ((int)0x80131014L);
+ const int COR_E_APPLICATION = unchecked ((int)0x80131600L);
+ const int E_INVALIDARG = unchecked ((int)0x80070057);
+ const int COR_E_ARGUMENTOUTOFRANGE = unchecked ((int)0x80131502L);
+ const int COR_E_ARITHMETIC = unchecked ((int)0x80070216);
+ const int COR_E_ARRAYTYPEMISMATCH = unchecked ((int)0x80131503L);
+ const int COR_E_BADIMAGEFORMAT = unchecked ((int)0x8007000BL);
+ const int ERROR_BAD_FORMAT = unchecked ((int)0x0B);
+ //const int COR_E_COMEMULATE_ERROR = unchecked ((int)?);
+ const int COR_E_CONTEXTMARSHAL = unchecked ((int)0x80131504L);
+ //const int COR_E_CORE = unchecked ((int)?);
+ const int NTE_FAIL = unchecked ((int)0x80090020L);
+ const int COR_E_DIRECTORYNOTFOUND = unchecked ((int)0x80070003L);
+ const int ERROR_PATH_NOT_FOUND = unchecked ((int)0x03);
+ const int COR_E_DIVIDEBYZERO = unchecked ((int)0x80020012L);
+ const int COR_E_DUPLICATEWAITOBJECT = unchecked ((int)0x80131529L);
+ const int COR_E_ENDOFSTREAM = unchecked ((int)0x80070026L);
+ const int COR_E_TYPELOAD = unchecked ((int)0x80131522L);
+ const int COR_E_EXCEPTION = unchecked ((int)0x80131500L);
+ const int COR_E_EXECUTIONENGINE = unchecked ((int)0x80131506L);
+ const int COR_E_FIELDACCESS = unchecked ((int)0x80131507L);
+ const int COR_E_FILENOTFOUND = unchecked ((int)0x80070002L);
+ const int ERROR_FILE_NOT_FOUND = unchecked ((int)0x02);
+ const int COR_E_FORMAT = unchecked ((int)0x80131537L);
+ const int COR_E_INDEXOUTOFRANGE = unchecked ((int)0x80131508L);
+ const int COR_E_INVALIDCAST = unchecked ((int)0x80004002L);
+ const int COR_E_INVALIDCOMOBJECT = unchecked ((int)0x80131527L);
+ const int COR_E_INVALIDFILTERCRITERIA = unchecked ((int)0x80131601L);
+ const int COR_E_INVALIDOLEVARIANTTYPE = unchecked ((int)0x80131531L);
+ const int COR_E_INVALIDOPERATION = unchecked ((int)0x80131509L);
+ const int COR_E_IO = unchecked ((int)0x80131620L);
+ const int COR_E_MEMBERACCESS = unchecked ((int)0x8013151AL);
+ const int COR_E_METHODACCESS = unchecked ((int)0x80131510L);
+ const int COR_E_MISSINGFIELD = unchecked ((int)0x80131511L);
+ const int COR_E_MISSINGMANIFESTRESOURCE = unchecked ((int)0x80131532L);
+ const int COR_E_MISSINGMEMBER = unchecked ((int)0x80131512L);
+ const int COR_E_MISSINGMETHOD = unchecked ((int)0x80131513L);
+ const int COR_E_MULTICASTNOTSUPPORTED = unchecked ((int)0x80131514L);
+ const int COR_E_NOTFINITENUMBER = unchecked ((int)0x80131528L);
+ const int E_NOTIMPL = unchecked ((int)0x80004001L);
+ const int COR_E_NOTSUPPORTED = unchecked ((int)0x80131515L);
+ const int COR_E_NULLREFERENCE = unchecked ((int)0x80004003L);
const int E_OUTOFMEMORY = unchecked ((int)0x8007000EL);
- const int E_INVALIDARG = unchecked ((int)0X80070057);
-
- switch (errorCode)
- {
- case E_OUTOFMEMORY:
- return new OutOfMemoryException ();
- case E_INVALIDARG:
- return new ArgumentException ();
+ const int COR_E_OVERFLOW = unchecked ((int)0x80131516L);
+ const int COR_E_PATHTOOLONG = unchecked ((int)0x800700CEL);
+ const int ERROR_FILENAME_EXCED_RANGE = unchecked ((int)0xCE);
+ const int COR_E_RANK = unchecked ((int)0x80131517L);
+ const int COR_E_REFLECTIONTYPELOAD = unchecked ((int)0x80131602L);
+ const int COR_E_REMOTING = unchecked ((int)0x8013150BL);
+ const int COR_E_SAFEARRAYTYPEMISMATCH = unchecked ((int)0x80131533L);
+ const int COR_E_SECURITY = unchecked ((int)0x8013150AL);
+ const int COR_E_SERIALIZATION = unchecked ((int)0x8013150CL);
+ const int COR_E_STACKOVERFLOW = unchecked ((int)0x800703E9L);
+ const int ERROR_STACK_OVERFLOW = unchecked ((int)0x03E9);
+ const int COR_E_SYNCHRONIZATIONLOCK = unchecked ((int)0x80131518L);
+ const int COR_E_SYSTEM = unchecked ((int)0x80131501L);
+ const int COR_E_TARGET = unchecked ((int)0x80131603L);
+ const int COR_E_TARGETINVOCATION = unchecked ((int)0x80131604L);
+ const int COR_E_TARGETPARAMCOUNT = unchecked ((int)0x8002000EL);
+ const int COR_E_THREADABORTED = unchecked ((int)0x80131530L);
+ const int COR_E_THREADINTERRUPTED = unchecked ((int)0x80131519L);
+ const int COR_E_THREADSTATE = unchecked ((int)0x80131520L);
+ const int COR_E_THREADSTOP = unchecked ((int)0x80131521L);
+ const int COR_E_TYPEINITIALIZATION = unchecked ((int)0x80131534L);
+ const int COR_E_VERIFICATION = unchecked ((int)0x8013150DL);
+ //const int COR_E_WEAKREFERENCE = unchecked ((int)?);
+ //const int COR_E_VTABLECALLSNOTSUPPORTED = unchecked ((int));
+
+ switch (errorCode) {
+ case MSEE_E_APPDOMAINUNLOADED:
+ return new AppDomainUnloadedException ();
+ case COR_E_APPLICATION:
+ return new ApplicationException ();
+ case E_INVALIDARG:
+ return new ArgumentException ();
+ case COR_E_ARGUMENTOUTOFRANGE:
+ return new ArgumentOutOfRangeException ();
+ case COR_E_ARITHMETIC:
+ return new ArithmeticException ();
+ case COR_E_ARRAYTYPEMISMATCH:
+ return new ArrayTypeMismatchException ();
+ case COR_E_BADIMAGEFORMAT:
+ case ERROR_BAD_FORMAT:
+ return new BadImageFormatException ();
+// case COR_E_COMEMULATE_ERROR:
+// return new COMEmulateException ();
+ case COR_E_CONTEXTMARSHAL:
+ return new ContextMarshalException ();
+// case COR_E_CORE:
+// return new CoreException ();
+ case NTE_FAIL:
+ return new System.Security.Cryptography.CryptographicException ();
+ case COR_E_DIRECTORYNOTFOUND:
+ case ERROR_PATH_NOT_FOUND:
+ return new System.IO.DirectoryNotFoundException ();
+ case COR_E_DIVIDEBYZERO:
+ return new DivideByZeroException ();
+ case COR_E_DUPLICATEWAITOBJECT:
+ return new DuplicateWaitObjectException ();
+ case COR_E_ENDOFSTREAM:
+ return new System.IO.EndOfStreamException ();
+ case COR_E_EXCEPTION:
+ return new Exception ();
+ case COR_E_EXECUTIONENGINE:
+ return new ExecutionEngineException ();
+ case COR_E_FIELDACCESS:
+ return new FieldAccessException ();
+ case COR_E_FILENOTFOUND:
+ case ERROR_FILE_NOT_FOUND:
+ return new System.IO.FileNotFoundException ();
+ case COR_E_FORMAT:
+ return new FormatException ();
+ case COR_E_INDEXOUTOFRANGE:
+ return new IndexOutOfRangeException ();
+ case COR_E_INVALIDCAST:
+ // E_NOINTERFACE has same value as COR_E_INVALIDCAST
+ return new InvalidCastException ();
+ case COR_E_INVALIDCOMOBJECT:
+ return new InvalidComObjectException ();
+ case COR_E_INVALIDFILTERCRITERIA:
+ return new InvalidFilterCriteriaException ();
+ case COR_E_INVALIDOLEVARIANTTYPE:
+ return new InvalidOleVariantTypeException ();
+ case COR_E_INVALIDOPERATION:
+ return new InvalidOperationException ();
+ case COR_E_IO:
+ return new System.IO.IOException ();
+ case COR_E_MEMBERACCESS:
+ return new MemberAccessException ();
+ case COR_E_METHODACCESS:
+ return new MethodAccessException ();
+ case COR_E_MISSINGFIELD:
+ return new MissingFieldException ();
+ case COR_E_MISSINGMANIFESTRESOURCE:
+ return new System.Resources.MissingManifestResourceException ();
+ case COR_E_MISSINGMEMBER:
+ return new MissingMemberException ();
+ case COR_E_MISSINGMETHOD:
+ return new MissingMethodException ();
+ case COR_E_MULTICASTNOTSUPPORTED:
+ return new MulticastNotSupportedException ();
+ case COR_E_NOTFINITENUMBER:
+ return new NotFiniteNumberException ();
+ case E_NOTIMPL:
+ return new NotImplementedException ();
+ case COR_E_NOTSUPPORTED:
+ return new NotSupportedException ();
+ case COR_E_NULLREFERENCE:
+ // E_POINTER has the same value as COR_E_NULLREFERENCE
+ return new NullReferenceException ();
+ case E_OUTOFMEMORY:
+ // COR_E_OUTOFMEMORY has the same value as E_OUTOFMEMORY
+ return new OutOfMemoryException ();
+ case COR_E_OVERFLOW:
+ return new OverflowException ();
+ case COR_E_PATHTOOLONG:
+ case ERROR_FILENAME_EXCED_RANGE:
+ return new System.IO.PathTooLongException ();
+ case COR_E_RANK:
+ return new RankException ();
+ case COR_E_REFLECTIONTYPELOAD:
+ return new System.Reflection.ReflectionTypeLoadException (new Type[] { }, new Exception[] { });
+ case COR_E_REMOTING:
+ return new System.Runtime.Remoting.RemotingException ();
+ case COR_E_SAFEARRAYTYPEMISMATCH:
+ return new SafeArrayTypeMismatchException ();
+ case COR_E_SECURITY:
+ return new SecurityException ();
+ case COR_E_SERIALIZATION:
+ return new System.Runtime.Serialization.SerializationException ();
+ case COR_E_STACKOVERFLOW:
+ case ERROR_STACK_OVERFLOW:
+ return new StackOverflowException ();
+ case COR_E_SYNCHRONIZATIONLOCK:
+ return new SynchronizationLockException ();
+ case COR_E_SYSTEM:
+ return new SystemException ();
+ case COR_E_TARGET:
+ return new TargetException ();
+ case COR_E_TARGETINVOCATION:
+ return new System.Reflection.TargetInvocationException (null);
+ case COR_E_TARGETPARAMCOUNT:
+ return new TargetParameterCountException ();
+// case COR_E_THREADABORTED:
+// ThreadAbortException c'tor is inaccessible
+// return new System.Threading.ThreadAbortException ();
+ case COR_E_THREADINTERRUPTED:
+ return new ThreadInterruptedException ();
+ case COR_E_THREADSTATE:
+ return new ThreadStateException ();
+// case COR_E_THREADSTOP:
+// ThreadStopException does not exist
+// return new System.Threading.ThreadStopException ();
+ case COR_E_TYPELOAD:
+ return new TypeLoadException ();
+ // MSDN lists COR_E_TYPELOAD twice with different exceptions.
+ // return new EntryPointNotFoundException ();
+ case COR_E_TYPEINITIALIZATION:
+ return new TypeInitializationException("", null);
+ case COR_E_VERIFICATION:
+ return new VerificationException ();
+// case COR_E_WEAKREFERENCE:
+// return new WeakReferenceException ();
+// case COR_E_VTABLECALLSNOTSUPPORTED:
+// return new VTableCallsNotSupportedException ();
}
if (errorCode < 0)
return new COMException ("", errorCode);
return null;
}
+ [DllImport ("oleaut32.dll", CharSet=CharSet.Unicode, EntryPoint = "SetErrorInfo")]
+ static extern int _SetErrorInfo (int dwReserved,
+ [MarshalAs(UnmanagedType.Interface)] IErrorInfo pIErrorInfo);
+
+ [DllImport ("oleaut32.dll", CharSet=CharSet.Unicode, EntryPoint = "GetErrorInfo")]
+ static extern int _GetErrorInfo (int dwReserved,
+ [MarshalAs(UnmanagedType.Interface)] out IErrorInfo ppIErrorInfo);
+
+ static bool SetErrorInfoNotAvailable;
+ static bool GetErrorInfoNotAvailable;
+
+ internal static int SetErrorInfo (int dwReserved, IErrorInfo errorInfo)
+ {
+ int retVal = 0;
+ errorInfo = null;
+
+ if (SetErrorInfoNotAvailable)
+ return -1;
+
+ try {
+ retVal = _SetErrorInfo (dwReserved, errorInfo);
+ }
+ catch (Exception) {
+ // ignore any exception - probably there's no suitable SetErrorInfo
+ // method available.
+ SetErrorInfoNotAvailable = true;
+ }
+ return retVal;
+ }
+
+ internal static int GetErrorInfo (int dwReserved, out IErrorInfo errorInfo)
+ {
+ int retVal = 0;
+ errorInfo = null;
+
+ if (GetErrorInfoNotAvailable)
+ return -1;
+
+ try {
+ retVal = _GetErrorInfo (dwReserved, out errorInfo);
+ }
+ catch (Exception) {
+ // ignore any exception - probably there's no suitable GetErrorInfo
+ // method available.
+ GetErrorInfoNotAvailable = true;
+ }
+ return retVal;
+ }
+
+ public static Exception GetExceptionForHR (int errorCode)
+ {
+ return GetExceptionForHR (errorCode, IntPtr.Zero);
+ }
+
+ public static Exception GetExceptionForHR (int errorCode, IntPtr errorInfoPtr)
+ {
+ IErrorInfo errorInfo = null;
+ if (errorInfoPtr != (IntPtr)(-1)) {
+ if (errorInfoPtr == IntPtr.Zero) {
+ if (GetErrorInfo (0, out errorInfo) != 0) {
+ errorInfo = null;
+ }
+ } else {
+ errorInfo = Marshal.GetObjectForIUnknown (errorInfoPtr) as IErrorInfo;
+ }
+ }
+
+ if (errorInfo is ManagedErrorInfo && ((ManagedErrorInfo)errorInfo).Exception.hresult == errorCode) {
+ return ((ManagedErrorInfo)errorInfo).Exception;
+ }
+
+ Exception e = ConvertHrToException (errorCode);
+ if (errorInfo != null && e != null) {
+ uint helpContext;
+ errorInfo.GetHelpContext (out helpContext);
+ string str;
+ errorInfo.GetSource (out str);
+ e.Source = str;
+ errorInfo.GetDescription (out str);
+ e.SetMessage (str);
+ errorInfo.GetHelpFile (out str);
+
+ if (helpContext == 0) {
+ e.HelpLink = str;
+ } else {
+ e.HelpLink = string.Format ("{0}#{1}", str, helpContext);
+ }
+ }
+ return e;
+ }
+
#if !FULL_AOT_RUNTIME
public static int FinalReleaseComObject (object o)
{
throw new ArgumentNullException ("type");
if (value == null)
throw new ArgumentNullException ("value");
+
+ Properties = new Dictionary <string, string> ();
+
Type = type;
Value = value;
ValueType = valueType == null ? ClaimValueTypes.String : valueType;
}
}
}
-#endif
\ No newline at end of file
+#endif
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if NET_4_0
-
using System.Runtime.CompilerServices;
namespace System
#elif NET_4_0
[TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
#endif
- public class InvalidTimeZoneException : Exception
+#if NET_4_0
+ public
+#endif
+ class InvalidTimeZoneException : Exception
{
public InvalidTimeZoneException () : base ()
{}
{}
}
}
-
-#endif
return DateTime.SpecifyKind (DateTime.MinValue, DateTimeKind.Local);
}
- DateTime local = DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local);
- DaylightTime dlt = GetDaylightChanges (time.Year);
- if (dlt.Delta.Ticks == 0)
- return DateTime.SpecifyKind (local, DateTimeKind.Local);
-
- // FIXME: check all of the combination of
- // - basis: local-based or UTC-based
- // - hemisphere: Northern or Southern
- // - offset: positive or negative
-
- // PST should work fine here.
- if (local < dlt.End && dlt.End.Subtract (dlt.Delta) <= local)
- return DateTime.SpecifyKind (local, DateTimeKind.Local);
-
- TimeSpan localOffset = GetUtcOffset (local);
- return DateTime.SpecifyKind (time.Add (localOffset), DateTimeKind.Local);
+ return DateTime.SpecifyKind (time.Add (utcOffset), DateTimeKind.Local);
}
public virtual DateTime ToUniversalTime (DateTime time)
// A yearwise cache of DaylightTime.
private Dictionary<int, DaylightTime> m_CachedDaylightChanges = new Dictionary<int, DaylightTime> (1);
- // the offset when daylightsaving is not on (in ticks)
- private long m_ticksOffset;
-
- // the offset when daylightsaving is not on.
- [NonSerialized]
- private TimeSpan utcOffsetWithOutDLS;
-
- // the offset when daylightsaving is on.
- [NonSerialized]
- private TimeSpan utcOffsetWithDLS;
-
internal enum TimeZoneData
{
DaylightSavingStartIdx,
m_standardName = Locale.GetText (names[(int)TimeZoneNames.StandardNameIdx]);
m_daylightName = Locale.GetText (names[(int)TimeZoneNames.DaylightNameIdx]);
- m_ticksOffset = data[(int)TimeZoneData.UtcOffsetIdx];
-
DaylightTime dlt = GetDaylightTimeFromData (data);
m_CachedDaylightChanges.Add (now.Year, dlt);
OnDeserialization (dlt);
if (time.Kind == DateTimeKind.Utc)
return TimeSpan.Zero;
- if (IsDaylightSavingTime (time) && !IsAmbiguousTime (time))
- return utcOffsetWithDLS;
-
- return utcOffsetWithOutDLS;
- }
-
- private bool IsAmbiguousTime (DateTime time)
- {
- if (time.Kind == DateTimeKind.Utc)
- return false;
-
- DaylightTime changes = GetDaylightChanges (time.Year);
-
- return time < changes.End && time >= changes.End - changes.Delta;
+ return TimeZoneInfo.Local.GetUtcOffset (time);
}
void IDeserializationCallback.OnDeserialization (object sender)
} else
this_year = dlt.Start.Year;
- utcOffsetWithOutDLS = new TimeSpan (m_ticksOffset);
- utcOffsetWithDLS = new TimeSpan (m_ticksOffset + dlt.Delta.Ticks);
this_year_dlt = dlt;
}
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#if NET_4_0
using System.Runtime.CompilerServices;
#elif NET_4_0
[TypeForwardedFrom (Consts.AssemblySystemCore_3_5)]
#endif
- public class TimeZoneNotFoundException : Exception
+#if NET_4_0
+ public
+#endif
+ class TimeZoneNotFoundException : Exception
{
public TimeZoneNotFoundException () : base ()
{}
{}
}
}
-
-#endif
System.Runtime.InteropServices/IDispatchImplType.cs
System.Runtime.InteropServices/IDLDESC.cs
System.Runtime.InteropServices/IDLFLAG.cs
+System.Runtime.InteropServices/IErrorInfo.cs
System.Runtime.InteropServices/IMPLTYPEFLAGS.cs
System.Runtime.InteropServices/INVOKEKIND.cs
System.Runtime.InteropServices/IRegistrationServices.cs
System.Runtime.InteropServices/LCIDConversionAttribute.cs
System.Runtime.InteropServices/LIBFLAGS.cs
System.Runtime.InteropServices/LayoutKind.cs
+System.Runtime.InteropServices/ManagedErrorInfo.cs
System.Runtime.InteropServices/Marshal.cs
System.Runtime.InteropServices/MarshalAsAttribute.cs
System.Runtime.InteropServices/MarshalDirectiveException.cs
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
+ // FIXME: Too much code does this
+#if 0
if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
}
+#endif
}
g_free (ref_bitmap);
}
available_in_tlab = (int)(TLAB_REAL_END - TLAB_NEXT);//We'll never have tlabs > 2Gb
if (size > tlab_size || available_in_tlab > SGEN_MAX_NURSERY_WASTE) {
/* Allocate directly from the nursery */
- do {
- p = sgen_nursery_alloc (size);
- if (!p) {
- sgen_ensure_free_space (real_size);
- if (degraded_mode)
- return alloc_degraded (vtable, size, FALSE);
- else
- p = sgen_nursery_alloc (size);
- }
- } while (!p);
+ p = sgen_nursery_alloc (size);
if (!p) {
- // no space left
- g_assert (0);
+ /*
+ * We couldn't allocate from the nursery, so we try
+ * collecting. Even after the collection, we might
+ * still not have enough memory to allocate the
+ * object. The reason will most likely be that we've
+ * run out of memory, but there is the theoretical
+ * possibility that other threads might have consumed
+ * the freed up memory ahead of us, so doing another
+ * collection and trying again might actually help.
+ * Of course the same thing might happen again.
+ *
+ * Ideally we'd like to detect that case and loop (if
+ * we always loop we will loop endlessly in the case of
+ * OOM). What we do here is give up right away.
+ */
+ sgen_ensure_free_space (real_size);
+ if (degraded_mode)
+ return alloc_degraded (vtable, size, FALSE);
+ else
+ p = sgen_nursery_alloc (size);
}
+ SGEN_ASSERT (0, p, "Out of memory");
zero_tlab_if_necessary (p, size);
} else {
SGEN_LOG (3, "Retire TLAB: %p-%p [%ld]", TLAB_START, TLAB_REAL_END, (long)(TLAB_REAL_END - TLAB_NEXT - size));
sgen_nursery_retire_region (p, available_in_tlab);
- do {
- p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
- if (!p) {
- sgen_ensure_free_space (tlab_size);
- if (degraded_mode)
- return alloc_degraded (vtable, size, FALSE);
- else
- p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
- }
- } while (!p);
-
+ p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
if (!p) {
- // no space left
- g_assert (0);
+ /* See comment above in similar case. */
+ sgen_ensure_free_space (tlab_size);
+ if (degraded_mode)
+ return alloc_degraded (vtable, size, FALSE);
+ else
+ p = sgen_nursery_alloc_range (tlab_size, size, &alloc_size);
}
+ SGEN_ASSERT (0, p, "Out of memory");
/* Allocate a new TLAB from the current nursery fragment */
TLAB_START = (char*)p;
pin_objects_from_nursery_pin_queue (ScanCopyContext ctx)
{
GCMemSection *section = nursery_section;
- void **start = section->pin_queue_start;
- void **end = start + section->pin_queue_num_entries;
+ void **start = sgen_pinning_get_entry (section->pin_queue_first_entry);
+ void **end = sgen_pinning_get_entry (section->pin_queue_last_entry);
void *start_nursery = section->data;
void *end_nursery = section->next_data;
void *last = NULL;
{
size_t reduced_to;
- if (!nursery_section->pin_queue_num_entries)
+ if (nursery_section->pin_queue_first_entry == nursery_section->pin_queue_last_entry)
return;
reduced_to = pin_objects_from_nursery_pin_queue (ctx);
- nursery_section->pin_queue_num_entries = reduced_to;
- if (!reduced_to)
- nursery_section->pin_queue_start = NULL;
+ nursery_section->pin_queue_last_entry = nursery_section->pin_queue_first_entry + reduced_to;
}
if (G_UNLIKELY (do_pin_stats))
sgen_pin_stats_register_object (object, safe_object_get_size (object));
- GRAY_OBJECT_ENQUEUE (queue, object, sgen_obj_get_descriptor (object));
+ GRAY_OBJECT_ENQUEUE (queue, object, sgen_obj_get_descriptor_safe (object));
binary_protocol_pin (object, (gpointer)LOAD_VTABLE (object), safe_object_get_size (object));
#ifdef ENABLE_DTRACE
* next allocations.
*/
mono_profiler_gc_event (MONO_GC_EVENT_RECLAIM_START, 0);
- fragment_total = sgen_build_nursery_fragments (nursery_section,
- nursery_section->pin_queue_start, nursery_section->pin_queue_num_entries,
- unpin_queue);
+ fragment_total = sgen_build_nursery_fragments (nursery_section, unpin_queue);
if (!fragment_total)
degraded_mode = 1;
SGEN_LOG (6, "Pinning from large objects");
for (bigobj = los_object_list; bigobj; bigobj = bigobj->next) {
size_t dummy;
- if (sgen_find_optimized_pin_queue_area (bigobj->data, (char*)bigobj->data + sgen_los_object_size (bigobj), &dummy)) {
+ if (sgen_find_optimized_pin_queue_area (bigobj->data, (char*)bigobj->data + sgen_los_object_size (bigobj), &dummy, &dummy)) {
binary_protocol_pin (bigobj->data, (gpointer)LOAD_VTABLE (bigobj->data), safe_object_get_size (((MonoObject*)(bigobj->data))));
#ifdef ENABLE_DTRACE
if (objects_pinned) {
g_assert (!concurrent_collection_in_progress);
- /*This is slow, but we just OOM'd*/
+ /*
+ * This is slow, but we just OOM'd.
+ *
+ * See comment at `sgen_pin_queue_clear_discarded_entries` for how the pin
+ * queue is laid out at this point.
+ */
sgen_pin_queue_clear_discarded_entries (nursery_section, old_next_pin_slot);
+ /*
+ * We need to reestablish all pinned nursery objects in the pin queue
+ * because they're needed for fragment creation. Unpinning happens by
+ * walking the whole queue, so it's not necessary to reestablish where major
+ * heap block pins are - all we care is that they're still in there
+ * somewhere.
+ */
sgen_optimize_pin_queue ();
sgen_find_section_pin_queue_start_end (nursery_section);
objects_pinned = 0;
* pinned objects as we go, memzero() the empty fragments so they are ready for the
* next allocations.
*/
- if (!sgen_build_nursery_fragments (nursery_section, nursery_section->pin_queue_start, nursery_section->pin_queue_num_entries, NULL))
+ if (!sgen_build_nursery_fragments (nursery_section, NULL))
degraded_mode = 1;
/* prepare the pin queue for the next collection */
*/
char **scan_starts;
/* in major collections indexes in the pin_queue for objects that pin this section */
- void **pin_queue_start;
- size_t pin_queue_num_entries;
+ size_t pin_queue_first_entry;
+ size_t pin_queue_last_entry;
size_t num_scan_start;
};
void* sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure) MONO_INTERNAL;
void sgen_free_internal_dynamic (void *addr, size_t size, int type) MONO_INTERNAL;
-void** sgen_find_optimized_pin_queue_area (void *start, void *end, size_t *num) MONO_INTERNAL;
-void sgen_find_section_pin_queue_start_end (GCMemSection *section) MONO_INTERNAL;
-void sgen_pin_objects_in_section (GCMemSection *section, ScanCopyContext ctx) MONO_INTERNAL;
-
void sgen_pin_stats_register_object (char *obj, size_t size);
void sgen_pin_stats_register_global_remset (char *obj);
void sgen_pin_stats_print_class_stats (void);
void sgen_clear_nursery_fragments (void) MONO_INTERNAL;
void sgen_nursery_allocator_prepare_for_pinning (void) MONO_INTERNAL;
void sgen_nursery_allocator_set_nursery_bounds (char *nursery_start, char *nursery_end) MONO_INTERNAL;
-mword sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_t num_entries, SgenGrayQueue *unpin_queue) MONO_INTERNAL;
+mword sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpin_queue) MONO_INTERNAL;
void sgen_init_nursery_allocator (void) MONO_INTERNAL;
void sgen_nursery_allocator_init_heavy_stats (void) MONO_INTERNAL;
void sgen_alloc_init_heavy_stats (void) MONO_INTERNAL;
#include "metadata/sgen-layout-stats.h"
#include "metadata/gc-internal.h"
#include "metadata/sgen-pointer-queue.h"
+#include "metadata/sgen-pinning.h"
#define SGEN_HAVE_CONCURRENT_MARK
struct _MSBlockInfo {
int obj_size;
int obj_size_index;
- size_t pin_queue_num_entries;
unsigned int pinned : 1;
unsigned int has_references : 1;
unsigned int has_pinned : 1; /* means cannot evacuate */
char *block;
void **free_list;
MSBlockInfo *next_free;
- void **pin_queue_start;
+ size_t pin_queue_first_entry;
+ size_t pin_queue_last_entry;
#ifdef SGEN_HAVE_CONCURRENT_MARK
guint8 *cardtable_mod_union;
#endif
static void
mark_pinned_objects_in_block (MSBlockInfo *block, SgenGrayQueue *queue)
{
- int i;
+ void **entry, **end;
int last_index = -1;
- if (!block->pin_queue_num_entries)
+ if (block->pin_queue_first_entry == block->pin_queue_last_entry)
return;
block->has_pinned = TRUE;
- for (i = 0; i < block->pin_queue_num_entries; ++i) {
- int index = MS_BLOCK_OBJ_INDEX (block->pin_queue_start [i], block);
+ entry = sgen_pinning_get_entry (block->pin_queue_first_entry);
+ end = sgen_pinning_get_entry (block->pin_queue_last_entry);
+
+ for (; entry < end; ++entry) {
+ int index = MS_BLOCK_OBJ_INDEX (*entry, block);
char *obj;
- SGEN_ASSERT (9, index >= 0 && index < MS_BLOCK_FREE / block->obj_size, "invalid object %p index %d max-index %d", block->pin_queue_start [i], index, MS_BLOCK_FREE / block->obj_size);
+ SGEN_ASSERT (9, index >= 0 && index < MS_BLOCK_FREE / block->obj_size, "invalid object %p index %d max-index %d", *entry, index, MS_BLOCK_FREE / block->obj_size);
if (index == last_index)
continue;
obj = MS_BLOCK_OBJ (block, index);
MSBlockInfo *block;
FOREACH_BLOCK (block) {
- block->pin_queue_start = sgen_find_optimized_pin_queue_area (MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SKIP, MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE,
- &block->pin_queue_num_entries);
+ sgen_find_optimized_pin_queue_area (MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SKIP, MS_BLOCK_FOR_BLOCK_INFO (block) + MS_BLOCK_SIZE,
+ &block->pin_queue_first_entry, &block->pin_queue_last_entry);
} END_FOREACH_BLOCK;
}
#include "metadata/sgen-archdep.h"
#include "metadata/sgen-bridge.h"
#include "metadata/sgen-memory-governor.h"
+#include "metadata/sgen-pinning.h"
#include "metadata/mono-gc.h"
#include "metadata/method-builder.h"
#include "metadata/profiler-private.h"
}
mword
-sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, size_t num_entries, SgenGrayQueue *unpin_queue)
+sgen_build_nursery_fragments (GCMemSection *nursery_section, SgenGrayQueue *unpin_queue)
{
char *frag_start, *frag_end;
size_t frag_size;
- size_t i = 0;
SgenFragment *frags_ranges;
+ void **pin_start, **pin_entry, **pin_end;
#ifdef NALLOC_DEBUG
reset_alloc_records ();
/* clear scan starts */
memset (nursery_section->scan_starts, 0, nursery_section->num_scan_start * sizeof (gpointer));
- while (i < num_entries || frags_ranges) {
+ pin_start = pin_entry = sgen_pinning_get_entry (nursery_section->pin_queue_first_entry);
+ pin_end = sgen_pinning_get_entry (nursery_section->pin_queue_last_entry);
+
+ while (pin_entry < pin_end || frags_ranges) {
char *addr0, *addr1;
size_t size;
SgenFragment *last_frag = NULL;
addr0 = addr1 = sgen_nursery_end;
- if (i < num_entries)
- addr0 = start [i];
+ if (pin_entry < pin_end)
+ addr0 = *pin_entry;
if (frags_ranges)
addr1 = frags_ranges->fragment_start;
CANARIFY_SIZE (size);
sgen_set_nursery_scan_start (addr0);
frag_end = addr0;
- ++i;
+ ++pin_entry;
} else {
frag_end = addr1;
size = frags_ranges->fragment_next - addr1;
frag_size = size;
#ifdef NALLOC_DEBUG
- add_alloc_record (start [i], frag_size, PINNING);
+ add_alloc_record (*pin_entry, frag_size, PINNING);
#endif
frag_start = frag_end + frag_size;
}
sgen_minor_collector.build_fragments_finish (&mutator_allocator);
if (!unmask (mutator_allocator.alloc_head)) {
- SGEN_LOG (1, "Nursery fully pinned (%zd)", num_entries);
- for (i = 0; i < num_entries; ++i) {
- SGEN_LOG (3, "Bastard pinning obj %p (%s), size: %zd", start [i], sgen_safe_name (start [i]), sgen_safe_object_get_size (start [i]));
+ SGEN_LOG (1, "Nursery fully pinned");
+ for (pin_entry = pin_start; pin_entry < pin_end; ++pin_entry) {
+ void *p = *pin_entry;
+ SGEN_LOG (3, "Bastard pinning obj %p (%s), size: %zd", p, sgen_safe_name (p), sgen_safe_object_get_size (p));
}
}
return fragment_total;
sgen_pointer_queue_add (&pin_queue, ptr);
}
+gboolean
+sgen_find_optimized_pin_queue_area (void *start, void *end, size_t *first_out, size_t *last_out)
+{
+ size_t first = sgen_pointer_queue_search (&pin_queue, start);
+ size_t last = sgen_pointer_queue_search (&pin_queue, end);
+ SGEN_ASSERT (0, last == pin_queue.next_slot || pin_queue.data [last] >= end, "Pin queue search gone awry");
+ *first_out = first;
+ *last_out = last;
+ return first != last;
+}
+
void**
-sgen_find_optimized_pin_queue_area (void *start, void *end, size_t *num)
+sgen_pinning_get_entry (size_t index)
{
- size_t first, last;
- first = sgen_pointer_queue_search (&pin_queue, start);
- last = sgen_pointer_queue_search (&pin_queue, end);
- *num = last - first;
- if (first == last)
- return NULL;
- return pin_queue.data + first;
+ SGEN_ASSERT (0, index <= pin_queue.next_slot, "Pin queue entry out of range");
+ return &pin_queue.data [index];
}
void
sgen_find_section_pin_queue_start_end (GCMemSection *section)
{
SGEN_LOG (6, "Pinning from section %p (%p-%p)", section, section->data, section->end_data);
- section->pin_queue_start = sgen_find_optimized_pin_queue_area (section->data, section->end_data, §ion->pin_queue_num_entries);
- SGEN_LOG (6, "Found %zd pinning addresses in section %p", section->pin_queue_num_entries, section);
+
+ sgen_find_optimized_pin_queue_area (section->data, section->end_data,
+ §ion->pin_queue_first_entry, §ion->pin_queue_last_entry);
+
+ SGEN_LOG (6, "Found %zd pinning addresses in section %p",
+ section->pin_queue_last_entry - section->pin_queue_first_entry, section);
}
/*This will setup the given section for the while pin queue. */
void
sgen_pinning_setup_section (GCMemSection *section)
{
- section->pin_queue_start = pin_queue.data;
- section->pin_queue_num_entries = pin_queue.next_slot;
+ section->pin_queue_first_entry = 0;
+ section->pin_queue_last_entry = pin_queue.next_slot;
}
void
sgen_pinning_trim_queue_to_section (GCMemSection *section)
{
- pin_queue.next_slot = section->pin_queue_num_entries;
+ SGEN_ASSERT (0, section->pin_queue_first_entry == 0, "Pin queue trimming assumes the whole pin queue is used by the nursery");
+ pin_queue.next_slot = section->pin_queue_last_entry;
}
+/*
+ * This is called when we've run out of memory during a major collection.
+ *
+ * After collecting potential pin entries and sorting the array, this is what it looks like:
+ *
+ * +--------------------+---------------------------------------------+--------------------+
+ * | major heap entries | nursery entries | major heap entries |
+ * +--------------------+---------------------------------------------+--------------------+
+ *
+ * Of course there might not be major heap entries before and/or after the nursery entries,
+ * depending on where the major heap sections are in the address space, and whether there
+ * were any potential pointers there.
+ *
+ * When we pin nursery objects, we compact the nursery part of the pin array, which leaves
+ * discarded entries after the ones that actually pointed to nursery objects:
+ *
+ * +--------------------+-----------------+---------------------------+--------------------+
+ * | major heap entries | nursery entries | discarded nursery entries | major heap entries |
+ * +--------------------+-----------------+---------------------------+--------------------+
+ *
+ * When, due to being out of memory, we late pin more objects, the pin array looks like
+ * this:
+ *
+ * +--------------------+-----------------+---------------------------+--------------------+--------------+
+ * | major heap entries | nursery entries | discarded nursery entries | major heap entries | late entries |
+ * +--------------------+-----------------+---------------------------+--------------------+--------------+
+ *
+ * This function gets rid of the discarded nursery entries by nulling them out. Note that
+ * we can late pin objects not only in the nursery but also in the major heap, which happens
+ * when evacuation fails.
+ */
void
sgen_pin_queue_clear_discarded_entries (GCMemSection *section, size_t max_pin_slot)
{
- void **start = section->pin_queue_start + section->pin_queue_num_entries;
- void **end = pin_queue.data + max_pin_slot;
+ void **start = sgen_pinning_get_entry (section->pin_queue_last_entry);
+ void **end = sgen_pinning_get_entry (max_pin_slot);
void *addr;
- if (!start)
- return;
-
for (; start < end; ++start) {
addr = *start;
if ((char*)addr < section->data || (char*)addr > section->end_data)
void sgen_dump_pin_queue (void) MONO_INTERNAL;
+gboolean sgen_find_optimized_pin_queue_area (void *start, void *end, size_t *first_out, size_t *last_out) MONO_INTERNAL;
+void sgen_find_section_pin_queue_start_end (GCMemSection *section) MONO_INTERNAL;
+void** sgen_pinning_get_entry (size_t index) MONO_INTERNAL;
+void sgen_pin_objects_in_section (GCMemSection *section, ScanCopyContext ctx) MONO_INTERNAL;
+
/* Pinning stats */
void sgen_pin_stats_register_address (char *addr, int pin_type) MONO_INTERNAL;
#include <glib.h>
#include <string.h>
#include <stdlib.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#include <errno.h>
-
-#include <sys/types.h>
#ifdef HOST_WIN32
#include <ws2tcpip.h>
#else
#include <netdb.h>
#include <arpa/inet.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include <sys/types.h>
#include <mono/metadata/object.h>
#include <mono/io-layer/io-layer.h>
gint8 nthreads_diff;
} SamplesHistory;
+/*
+ * returns :
+ * - 1 if the number of threads should increase
+ * - 0 if it should not change
+ * - -1 if it should decrease
+ * - -2 in case of error
+ */
static gint8
monitor_heuristic (gint16 *current, gint16 *history_size, SamplesHistory *history, ThreadPool *tp)
{
decision = 2;
} else {
mono_mutex_lock (&threads_lock);
+ if (threads == NULL) {
+ mono_mutex_unlock (&threads_lock);
+ return -2;
+ }
all_waitsleepjoin = TRUE;
for (i = 0; i < threads->len; ++i) {
thread = g_ptr_array_index (threads, i);
if (suspended)
continue;
+ /* threadpool is cleaning up */
+ if (async_tp.pool_status == 2 || async_io_tp.pool_status == 2)
+ break;
+
switch (monitor_state) {
case MONITOR_STATE_AWAKE:
num_waiting_iterations = 0;
} else {
gint8 nthreads_diff = monitor_heuristic (¤t, &history_size, history, tp);
- if (nthreads_diff > 0)
+ if (nthreads_diff == 1)
threadpool_start_thread (tp);
- else if (nthreads_diff < 0)
+ else if (nthreads_diff == -1)
threadpool_kill_thread (tp);
}
}
mono_mutex_init (&threads_lock);
threads = g_ptr_array_sized_new (thread_count);
+ g_assert (threads);
mono_mutex_init_recursive (&wsqs_lock);
wsqs = g_ptr_array_sized_new (MAX (100 * cpu_count, thread_count));
thread = mono_thread_create_internal (mono_get_root_domain (), tp->async_invoke, tp, TRUE, stack_size);
if (!tp->is_io) {
mono_mutex_lock (&threads_lock);
+ g_assert (threads != NULL);
g_ptr_array_add (threads, thread);
mono_mutex_unlock (&threads_lock);
}
if (tp_finish_func)
tp_finish_func (tp_hooks_user_data);
- mono_mutex_lock (&threads_lock);
- g_ptr_array_remove_fast (threads, mono_thread_current ()->internal_thread);
- mono_mutex_unlock (&threads_lock);
+ if (!tp->is_io) {
+ if (threads) {
+ mono_mutex_lock (&threads_lock);
+ if (threads)
+ g_ptr_array_remove_fast (threads, mono_thread_current ()->internal_thread);
+ mono_mutex_unlock (&threads_lock);
+ }
+ }
return;
}
s390x_sources = \
mini-s390x.c \
mini-s390x.h \
+ support-s390x.h \
exceptions-s390x.c \
tramp-s390x.c
* Copyright 2011 Xamarin Inc (http://www.xamarin.com)
*/
-/* Remaining AOT-only work:
- * - optimize the trampolines, generate more code in the arch files.
- * - make things more consistent with how elf works, for example, use ELF
- * relocations.
- * Remaining generics sharing work:
- * - optimize the size of the data which is encoded.
- * - optimize the runtime loading of data:
- * - the trampoline code calls mono_jit_info_table_find () to find the rgctx,
- * which loads the debugging+exception handling info for the method. This is a
- * huge waste of time and code, since the rgctx structure is currently empty.
- */
#include "config.h"
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
#include <errno.h>
#include <sys/stat.h>
-
#include <mono/metadata/abi-details.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/class.h>
g_assert (code - buf == 8);
emit_bytes (acfg, buf, code - buf);
}
+
+ acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_SPECIFIC] = 16;
+ acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_STATIC_RGCTX] = 16;
+ acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_IMT_THUNK] = 72;
+ acfg->tramp_page_code_offsets [MONO_AOT_TRAMP_GSHAREDVT_ARG] = 16;
#elif defined(TARGET_ARM64)
arm64_emit_specific_trampoline_pages (acfg);
#endif
#include <mach/mach.h>
static TrampolinePage* trampoline_pages [MONO_AOT_TRAMP_NUM];
-/* these sizes are for ARM code, parametrize if porting to other architectures (see arch_emit_specific_trampoline_pages)
- * trampoline size is assumed to be 8 bytes below as well (8 is the minimum for 32 bit archs, since we need to store
- * two pointers for trampoline in the data page).
- * the minimum for the common code must be at least sizeof(TrampolinePage), since we store the page info at the
- * beginning of the data page.
- */
-static const int trampolines_pages_code_offsets [MONO_AOT_TRAMP_NUM] = {16, 16, 72, 16};
static unsigned char*
get_new_trampoline_from_page (int tramp_type)
page = (TrampolinePage*)addr;
page->next = trampoline_pages [tramp_type];
trampoline_pages [tramp_type] = page;
-#ifdef TARGET_ARM64
page->trampolines = (void*)(taddr + amodule->info.tramp_page_code_offsets [tramp_type]);
-#else
- page->trampolines = (void*)(taddr + trampolines_pages_code_offsets [tramp_type]);
-#endif
page->trampolines_end = (void*)(taddr + psize - 64);
code = page->trampolines;
page->trampolines += specific_trampoline_size;
long_neg: dest:i src1:i len:6
long_not: dest:i src1:i len:12
long_rem: dest:i src1:i src2:i len:12
+long_rem_imm: dest:i src1:i src2:i len:12
long_rem_un: dest:i src1:i src2:i len:16
long_shl: dest:i src1:i src2:i len:14
long_shl_imm: dest:i src1:i len:14
ins->opcode = OP_ICONST;
MONO_INST_NULLIFY_SREGS (ins);
ins->inst_c0 = 0;
+#if __s390__
+ }
+#else
} else if ((ins->inst_imm > 0) && (ins->inst_imm < (1LL << 32)) && (power != -1)) {
gboolean is_long = ins->opcode == OP_LREM_IMM;
int compensator_reg = alloc_ireg (cfg);
if (power > 1) {
intermediate_reg = compensator_reg;
- MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_SHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_IMM : OP_ISHR_IMM, intermediate_reg, ins->sreg1, is_long ? 63 : 31);
} else {
intermediate_reg = ins->sreg1;
}
- MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_SHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
+ MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LSHR_UN_IMM : OP_ISHR_UN_IMM, compensator_reg, intermediate_reg, (is_long ? 64 : 32) - power);
MONO_EMIT_NEW_BIALU (cfg, is_long ? OP_LADD : OP_IADD, ins->dreg, ins->sreg1, compensator_reg);
/* Compute remainder */
MONO_EMIT_NEW_BIALU_IMM (cfg, is_long ? OP_LAND_IMM : OP_AND_IMM, ins->dreg, ins->dreg, (1 << power) - 1);
NULLIFY_INS (ins);
}
+#endif
break;
}
#include "mini-llvm-cpp.h"
-#define LLVM_CHECK_VERSION(major,minor) \
- ((LLVM_MAJOR_VERSION > (major)) || \
- ((LLVM_MAJOR_VERSION == (major)) && (LLVM_MINOR_VERSION >= (minor))))
-
// extern "C" void LLVMInitializeARMTargetInfo();
// extern "C" void LLVMInitializeARMTarget ();
// extern "C" void LLVMInitializeARMTargetMC ();
// EngineBuilder no longer has a copy assignment operator (?)
std::unique_ptr<Module> Owner(unwrap(MP));
EngineBuilder b (std::move(Owner));
- EngineBuilder &eb = b;
#ifdef TARGET_AMD64
ExecutionEngine *EE = b.setJITMemoryManager (mono_mm).setTargetOptions (opts).setAllocateGVsWithCode (true).setMCPU (cpu_name).setCodeModel (CodeModel::Large).create ();
#else
switch (t->type) {
case MONO_TYPE_U1:
case MONO_TYPE_U2:
+ case MONO_TYPE_CHAR:
case MONO_TYPE_U4:
case MONO_TYPE_U8:
return TRUE;
type_to_llvm_arg_type (EmitContext *ctx, MonoType *t)
{
LLVMTypeRef ptype = type_to_llvm_type (ctx, t);
-
+
+ /*
+ * This works on all abis except arm64/ios which passes multiple
+ * arguments in one stack slot.
+ */
+#ifndef TARGET_ARM64
if (ptype == LLVMInt8Type () || ptype == LLVMInt16Type ()) {
/*
* LLVM generates code which only sets the lower bits, while JITted
*/
ptype = LLVMInt32Type ();
}
+#endif
return ptype;
}
ctx->values [reg] = LLVMBuildLoad (builder, ctx->addresses [reg], "");
}
} else {
- ctx->values [reg] = convert (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i])));
+ ctx->values [reg] = convert_full (ctx, ctx->values [reg], llvm_type_to_stack_type (type_to_llvm_type (ctx, sig->params [i])), type_is_unsigned (ctx, sig->params [i]));
}
}
LLVMValueRef lmethod;
lmethod = g_hash_table_lookup (module->method_to_lmethod, ji->data.method);
- if (lmethod) {
+ /* The types might not match because the caller might pass an rgctx */
+ if (lmethod && LLVMTypeOf (callee) == LLVMTypeOf (lmethod)) {
mono_llvm_replace_uses_of (callee, lmethod);
mono_aot_mark_unused_llvm_plt_entry (ji);
}
if (diff < 0)
indent_level += diff;
v = indent_level;
- printf("%p [%3d] ",pthread_self(),v);
+ printf("%p [%3d] ",(void *)pthread_self(),v);
while (v-- > 0) {
printf (". ");
}
case OP_IREM_UN_IMM:
case OP_LAND_IMM:
case OP_LOR_IMM:
+ case OP_LREM_IMM:
case OP_LXOR_IMM:
case OP_LOCALLOC_IMM:
mono_decompose_op_imm (cfg, bb, ins);
s390_lgr (code, ins->dreg, s390_r0);
break;
}
+ case OP_LREM_IMM: {
+ if (s390_is_imm16 (ins->inst_imm)) {
+ s390_lghi (code, s390_r13, ins->inst_imm);
+ } else {
+ s390_lgfi (code, s390_r13, ins->inst_imm);
+ }
+ s390_lgr (code, s390_r0, ins->sreg1);
+ s390_dsgr (code, s390_r0, s390_r13);
+ s390_lgfr (code, ins->dreg, s390_r0);
+ }
+ break;
case OP_LREM_UN: {
s390_lgr (code, s390_r1, ins->sreg1);
s390_lghi (code, s390_r0, 0);
/*------------------------------------------------------------------*/
gpointer
-mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg)
+mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
+ int offset, gboolean load_imt_reg)
{
- return NULL;
+ guint8 *code, *start;
+ int size = 20;
+
+ start = code = mono_global_codeman_reserve (size);
+
+ /*
+ * Replace the "this" argument with the target
+ */
+ s390_lgr (code, s390_r1, s390_r2);
+ s390_lg (code, s390_r2, s390_r1, 0, MONO_STRUCT_OFFSET(MonoDelegate, target));
+
+ /*
+ * Load the IMT register, if needed
+ */
+ if (load_imt_reg) {
+ s390_lg (code, MONO_ARCH_IMT_REG, s390_r2, 0, MONO_STRUCT_OFFSET(MonoDelegate, method));
+ }
+
+ /*
+ * Load the vTable
+ */
+ s390_lg (code, s390_r1, s390_r2, 0, MONO_STRUCT_OFFSET(MonoObject, vtable));
+ s390_agfi(code, s390_r1, offset);
+ s390_br (code, s390_r1);
+
+ return(start);
}
/*========================= End of Function ========================*/
s390_lg (code, s390_r1, 0, s390_r1, 0);
}
s390_br (code, s390_r1);
- target = S390_RELATIVE(code, item->jmp_code);
+ target = (gint64) S390_RELATIVE(code, item->jmp_code);
s390_patch_rel(item->jmp_code+2, target);
S390_SET (code, s390_r1, fail_tramp);
s390_br (code, s390_r1);
if (item->jmp_code) {
if (item->check_target_idx) {
gint64 offset;
- offset = S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
+ offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
item->jmp_code);
s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
}
{
GSList *l = NULL;
- mono_add_unwind_op_def_cfa (l, NULL, NULL, STK_BASE, 0);
+ mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
return(l);
}
#define COMPILE_SOFT_FLOAT(cfg) (0)
#endif
-#ifdef ENABLE_LLVM
-#define LLVM_CHECK_VERSION(major,minor) \
- ((LLVM_MAJOR_VERSION > (major)) || \
- ((LLVM_MAJOR_VERSION == (major)) && (LLVM_MINOR_VERSION >= (minor))))
-#else
-#define LLVM_CHECK_VERSION(major,minor) 0
-#endif
-
#define NOT_IMPLEMENTED do { g_assert_not_reached (); } while (0)
/* for 32 bit systems */
#define S390_SET(loc, dr, v) \
do { \
guint64 val = (guint64) v; \
- if (s390_is_uimm16(val)) { \
+ if (s390_is_imm16(val)) { \
+ s390_lghi(loc, dr, val); \
+ } else if (s390_is_uimm16(val)) { \
s390_llill(loc, dr, val); \
+ } else if (s390_is_imm32(val)) { \
+ s390_lgfi(loc, dr, val); \
} else if (s390_is_uimm32(val)) { \
s390_llilf(loc, dr, val); \
} else { \
#if defined(TARGET_X86)
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__DragonFly__)
-#include <ucontext.h>
-#endif
#if defined(__APPLE__)
#include <AvailabilityMacros.h>
#endif
#define UCONTEXT_REG_EIP(ctx) (((ucontext_t*)(ctx))->uc_mcontext.gregs [EIP])
#else
-#if defined(PLATFORM_ANDROID)
+#if defined(PLATFORM_ANDROID) && !defined(HAVE_UCONTEXT_H)
/* No ucontext.h as of NDK v6b */
typedef int greg_t;
#define NGREG 19