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.
31 using System.Collections.Specialized;
33 using System.IO.Compression;
35 using System.Web.Configuration;
36 using System.Runtime.Remoting;
37 using System.Diagnostics;
39 namespace System.Web.SessionState
41 internal class SessionStateServerHandler : SessionStateStoreProviderBase
43 const Int32 lockAcquireTimeout = 30000;
45 SessionStateSection config;
46 RemoteStateServer stateServer;
48 public override SessionStateStoreData CreateNewStoreData (HttpContext context, int timeout)
50 return new SessionStateStoreData (new SessionStateItemCollection (),
51 HttpApplicationFactory.ApplicationState.SessionObjects,
55 public override void CreateUninitializedItem (HttpContext context, string id, int timeout)
57 EnsureGoodId (id, true);
58 stateServer.CreateUninitializedItem (id, timeout);
61 public override void Dispose ()
65 public override void EndRequest (HttpContext context)
69 SessionStateStoreData GetItemInternal (HttpContext context,
74 out SessionStateActions actions,
78 lockAge = TimeSpan.MinValue;
79 lockId = Int32.MinValue;
80 actions = SessionStateActions.None;
85 StateServerItem item = stateServer.GetItem (id,
95 if (actions == SessionStateActions.InitializeItem)
96 return CreateNewStoreData (context, item.Timeout);
98 SessionStateItemCollection items = null;
99 HttpStaticObjectsCollection sobjs = null;
100 MemoryStream stream = null;
101 BinaryReader reader = null;
104 GZipStream gzip = null;
107 if (item.CollectionData != null && item.CollectionData.Length > 0) {
108 stream = new MemoryStream (item.CollectionData);
110 if (config.CompressionEnabled)
111 input = gzip = new GZipStream (stream, CompressionMode.Decompress, true);
115 reader = new BinaryReader (input);
116 items = SessionStateItemCollection.Deserialize (reader);
123 items = new SessionStateItemCollection ();
124 if (item.StaticObjectsData != null && item.StaticObjectsData.Length > 0)
125 sobjs = HttpStaticObjectsCollection.FromByteArray (item.StaticObjectsData);
127 sobjs = new HttpStaticObjectsCollection ();
128 } catch (Exception ex) {
129 throw new HttpException ("Failed to retrieve session state.", ex);
140 ((IDisposable)reader).Dispose ();
144 return new SessionStateStoreData (items,
149 public override SessionStateStoreData GetItem (HttpContext context,
152 out TimeSpan lockAge,
154 out SessionStateActions actions)
156 EnsureGoodId (id, false);
157 return GetItemInternal (context, id, out locked, out lockAge, out lockId, out actions, false);
160 public override SessionStateStoreData GetItemExclusive (HttpContext context,
163 out TimeSpan lockAge,
165 out SessionStateActions actions)
167 EnsureGoodId (id, false);
168 return GetItemInternal (context, id, out locked, out lockAge, out lockId, out actions, true);
171 public override void Initialize (string name, NameValueCollection config)
173 this.config = (SessionStateSection) WebConfigurationManager.GetSection ("system.web/sessionState");
174 if (String.IsNullOrEmpty (name))
175 name = "Session Server handler";
176 RemotingConfiguration.Configure (null);
177 string cons = null, proto = null, server = null, port = null;
178 GetConData (out proto, out server, out port);
179 cons = String.Format ("{0}://{1}:{2}/StateServer", proto, server, port);
180 stateServer = Activator.GetObject (typeof (RemoteStateServer), cons) as RemoteStateServer;
182 base.Initialize (name, config);
185 public override void InitializeRequest (HttpContext context)
187 // nothing to do here
190 public override void ReleaseItemExclusive (HttpContext context,
194 EnsureGoodId (id, true);
195 stateServer.ReleaseItemExclusive (id, lockId);
198 public override void RemoveItem (HttpContext context,
201 SessionStateStoreData item)
203 EnsureGoodId (id, true);
204 stateServer.Remove (id, lockId);
207 public override void ResetItemTimeout (HttpContext context, string id)
209 EnsureGoodId (id, true);
210 stateServer.ResetItemTimeout (id);
213 public override void SetAndReleaseItemExclusive (HttpContext context,
215 SessionStateStoreData item,
222 EnsureGoodId (id, true);
223 byte[] collection_data = null;
224 byte[] sobjs_data = null;
225 MemoryStream stream = null;
226 BinaryWriter writer = null;
227 Stream output = null;
229 GZipStream gzip = null;
233 SessionStateItemCollection items = item.Items as SessionStateItemCollection;
234 if (items != null && items.Count > 0) {
235 stream = new MemoryStream ();
237 if (config.CompressionEnabled)
238 output = gzip = new GZipStream (stream, CompressionMode.Compress, true);
242 writer = new BinaryWriter (output);
243 items.Serialize (writer);
249 collection_data = stream.ToArray ();
251 HttpStaticObjectsCollection sobjs = item.StaticObjects;
252 if (sobjs != null && sobjs.Count > 0)
253 sobjs_data = sobjs.ToByteArray ();
254 } catch (Exception ex) {
255 throw new HttpException ("Failed to store session data.", ex);
265 ((IDisposable)writer).Dispose ();
271 stateServer.SetAndReleaseItemExclusive (id, collection_data, sobjs_data, lockId, item.Timeout, newItem);
274 public override bool SetItemExpireCallback (SessionStateItemExpireCallback expireCallback)
279 void EnsureGoodId (string id, bool throwOnNull)
283 throw new HttpException ("Session ID is invalid");
287 if (id.Length > SessionIDManager.SessionIDMaxLength)
288 throw new HttpException ("Session ID too long");
291 void GetConData (out string proto, out string server, out string port)
293 string cons = config.StateConnectionString;
294 int ei = cons.IndexOf ('=');
295 int ci = cons.IndexOf (':');
297 if (ei < 0 || ci < 0)
298 throw new HttpException ("Invalid StateConnectionString");
300 proto = cons.Substring (0, ei);
301 server = cons.Substring (ei+1, ci - ei - 1);
302 port = cons.Substring (ci+1, cons.Length - ci - 1);
304 if (proto == "tcpip")