2 // System.Web.SessionStateServerHandler
5 // Marek Habersack (grendello@gmail.com)
7 // (C) 2006 Marek Habersack
8 // (C) 2007-2010 Novell, Inc (http://novell.com/)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections.Specialized;
34 using System.IO.Compression;
36 using System.Web.Configuration;
37 using System.Runtime.Remoting;
38 using System.Diagnostics;
40 namespace System.Web.SessionState
42 internal class SessionStateServerHandler : SessionStateStoreProviderBase
44 const Int32 lockAcquireTimeout = 30000;
46 SessionStateSection config;
47 RemoteStateServer stateServer;
49 public override SessionStateStoreData CreateNewStoreData (HttpContext context, int timeout)
51 return new SessionStateStoreData (new SessionStateItemCollection (),
52 HttpApplicationFactory.ApplicationState.SessionObjects,
56 public override void CreateUninitializedItem (HttpContext context, string id, int timeout)
58 EnsureGoodId (id, true);
59 stateServer.CreateUninitializedItem (id, timeout);
62 public override void Dispose ()
66 public override void EndRequest (HttpContext context)
70 SessionStateStoreData GetItemInternal (HttpContext context,
75 out SessionStateActions actions,
79 lockAge = TimeSpan.MinValue;
80 lockId = Int32.MinValue;
81 actions = SessionStateActions.None;
86 StateServerItem item = stateServer.GetItem (id,
96 if (actions == SessionStateActions.InitializeItem)
97 return CreateNewStoreData (context, item.Timeout);
99 SessionStateItemCollection items = null;
100 HttpStaticObjectsCollection sobjs = null;
101 MemoryStream stream = null;
102 BinaryReader reader = null;
105 GZipStream gzip = null;
108 if (item.CollectionData != null && item.CollectionData.Length > 0) {
109 stream = new MemoryStream (item.CollectionData);
111 if (config.CompressionEnabled)
112 input = gzip = new GZipStream (stream, CompressionMode.Decompress, true);
116 reader = new BinaryReader (input);
117 items = SessionStateItemCollection.Deserialize (reader);
124 items = new SessionStateItemCollection ();
125 if (item.StaticObjectsData != null && item.StaticObjectsData.Length > 0)
126 sobjs = HttpStaticObjectsCollection.FromByteArray (item.StaticObjectsData);
128 sobjs = new HttpStaticObjectsCollection ();
129 } catch (Exception ex) {
130 throw new HttpException ("Failed to retrieve session state.", ex);
141 ((IDisposable)reader).Dispose ();
145 return new SessionStateStoreData (items,
150 public override SessionStateStoreData GetItem (HttpContext context,
153 out TimeSpan lockAge,
155 out SessionStateActions actions)
157 EnsureGoodId (id, false);
158 return GetItemInternal (context, id, out locked, out lockAge, out lockId, out actions, false);
161 public override SessionStateStoreData GetItemExclusive (HttpContext context,
164 out TimeSpan lockAge,
166 out SessionStateActions actions)
168 EnsureGoodId (id, false);
169 return GetItemInternal (context, id, out locked, out lockAge, out lockId, out actions, true);
172 public override void Initialize (string name, NameValueCollection config)
174 this.config = (SessionStateSection) WebConfigurationManager.GetSection ("system.web/sessionState");
175 if (String.IsNullOrEmpty (name))
176 name = "Session Server handler";
177 RemotingConfiguration.Configure (null);
178 string cons = null, proto = null, server = null, port = null;
179 GetConData (out proto, out server, out port);
180 cons = String.Format ("{0}://{1}:{2}/StateServer", proto, server, port);
181 stateServer = Activator.GetObject (typeof (RemoteStateServer), cons) as RemoteStateServer;
183 base.Initialize (name, config);
186 public override void InitializeRequest (HttpContext context)
188 // nothing to do here
191 public override void ReleaseItemExclusive (HttpContext context,
195 EnsureGoodId (id, true);
196 stateServer.ReleaseItemExclusive (id, lockId);
199 public override void RemoveItem (HttpContext context,
202 SessionStateStoreData item)
204 EnsureGoodId (id, true);
205 stateServer.Remove (id, lockId);
208 public override void ResetItemTimeout (HttpContext context, string id)
210 EnsureGoodId (id, true);
211 stateServer.ResetItemTimeout (id);
214 public override void SetAndReleaseItemExclusive (HttpContext context,
216 SessionStateStoreData item,
220 EnsureGoodId (id, true);
221 byte[] collection_data = null;
222 byte[] sobjs_data = null;
223 MemoryStream stream = null;
224 BinaryWriter writer = null;
225 Stream output = null;
227 GZipStream gzip = null;
231 SessionStateItemCollection items = item.Items as SessionStateItemCollection;
232 if (items != null && items.Count > 0) {
233 stream = new MemoryStream ();
235 if (config.CompressionEnabled)
236 output = gzip = new GZipStream (stream, CompressionMode.Compress, true);
240 writer = new BinaryWriter (output);
241 items.Serialize (writer);
247 collection_data = stream.ToArray ();
249 HttpStaticObjectsCollection sobjs = item.StaticObjects;
250 if (sobjs != null && sobjs.Count > 0)
251 sobjs_data = sobjs.ToByteArray ();
252 } catch (Exception ex) {
253 throw new HttpException ("Failed to store session data.", ex);
263 ((IDisposable)writer).Dispose ();
269 stateServer.SetAndReleaseItemExclusive (id, collection_data, sobjs_data, lockId, item.Timeout, newItem);
272 public override bool SetItemExpireCallback (SessionStateItemExpireCallback expireCallback)
277 void EnsureGoodId (string id, bool throwOnNull)
281 throw new HttpException ("Session ID is invalid");
285 if (id.Length > SessionIDManager.SessionIDMaxLength)
286 throw new HttpException ("Session ID too long");
289 void GetConData (out string proto, out string server, out string port)
291 string cons = config.StateConnectionString;
292 int ei = cons.IndexOf ('=');
293 int ci = cons.IndexOf (':');
295 if (ei < 0 || ci < 0)
296 throw new HttpException ("Invalid StateConnectionString");
298 proto = cons.Substring (0, ei);
299 server = cons.Substring (ei+1, ci - ei - 1);
300 port = cons.Substring (ci+1, cons.Length - ci - 1);
302 if (proto == "tcpip")