123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Security.Authentication;
- using System.Text;
- using System.Threading;
- using SuperSocket.Common;
- using SuperSocket.SocketBase.Command;
- using SuperSocket.SocketBase.Config;
- using SuperSocket.SocketBase.Logging;
- using SuperSocket.SocketBase.Protocol;
- namespace SuperSocket.SocketBase
- {
-
-
-
-
-
- public abstract class AppSession<TAppSession, TRequestInfo> : IAppSession, IAppSession<TAppSession, TRequestInfo>
- where TAppSession : AppSession<TAppSession, TRequestInfo>, IAppSession, new()
- where TRequestInfo : class, IRequestInfo
- {
- #region Properties
-
-
-
- public virtual AppServerBase<TAppSession, TRequestInfo> AppServer { get; private set; }
-
-
-
- IAppServer IAppSession.AppServer
- {
- get { return this.AppServer; }
- }
-
-
-
-
-
-
- public Encoding Charset { get; set; }
- private IDictionary<object, object> m_Items;
-
-
-
- public IDictionary<object, object> Items
- {
- get
- {
- if (m_Items == null)
- m_Items = new Dictionary<object, object>(10);
- return m_Items;
- }
- }
- private bool m_Connected = false;
-
-
-
-
-
-
- public bool Connected
- {
- get { return m_Connected; }
- internal set { m_Connected = value; }
- }
-
-
-
-
-
-
- public string PrevCommand { get; set; }
-
-
-
-
-
-
- public string CurrentCommand { get; set; }
-
-
-
-
-
-
- public SslProtocols SecureProtocol
- {
- get { return SocketSession.SecureProtocol; }
- set { SocketSession.SecureProtocol = value; }
- }
-
-
-
- public IPEndPoint LocalEndPoint
- {
- get { return SocketSession.LocalEndPoint; }
- }
-
-
-
- public IPEndPoint RemoteEndPoint
- {
- get { return SocketSession.RemoteEndPoint; }
- }
-
-
-
- public ILog Logger
- {
- get { return AppServer.Logger; }
- }
-
-
-
-
-
-
- public DateTime LastActiveTime { get; set; }
-
-
-
- public DateTime StartTime { get; private set; }
-
-
-
- public string SessionID { get; private set; }
-
-
-
- public ISocketSession SocketSession { get; private set; }
-
-
-
- public IServerConfig Config
- {
- get { return AppServer.Config; }
- }
- IReceiveFilter<TRequestInfo> m_ReceiveFilter;
- #endregion
-
-
-
- public AppSession()
- {
- this.StartTime = DateTime.Now;
- this.LastActiveTime = this.StartTime;
- }
-
-
-
-
-
- public virtual void Initialize(IAppServer<TAppSession, TRequestInfo> appServer, ISocketSession socketSession)
- {
- var castedAppServer = (AppServerBase<TAppSession, TRequestInfo>)appServer;
- AppServer = castedAppServer;
- Charset = castedAppServer.TextEncoding;
- SocketSession = socketSession;
- SessionID = socketSession.SessionID;
- m_Connected = true;
- m_ReceiveFilter = castedAppServer.ReceiveFilterFactory.CreateFilter(appServer, this, socketSession.RemoteEndPoint);
- var filterInitializer = m_ReceiveFilter as IReceiveFilterInitializer;
- if (filterInitializer != null)
- filterInitializer.Initialize(castedAppServer, this);
- socketSession.Initialize(this);
- OnInit();
- }
-
-
-
- void IAppSession.StartSession()
- {
- OnSessionStarted();
- }
-
-
-
- protected virtual void OnInit()
- {
-
- }
-
-
-
- protected virtual void OnSessionStarted()
- {
- }
-
-
-
-
- internal protected virtual void OnSessionClosed(CloseReason reason)
- {
- }
-
-
-
-
- protected virtual void HandleException(Exception e)
- {
- Logger.Error(this, e);
- this.Close(CloseReason.ApplicationError);
- }
-
-
-
-
- protected virtual void HandleUnknownRequest(TRequestInfo requestInfo)
- {
- }
- internal void InternalHandleUnknownRequest(TRequestInfo requestInfo)
- {
- HandleUnknownRequest(requestInfo);
- }
- internal void InternalHandleExcetion(Exception e)
- {
- HandleException(e);
- }
-
-
-
-
- public virtual void Close(CloseReason reason)
- {
- this.SocketSession.Close(reason);
- }
-
-
-
- public virtual void Close()
- {
- Close(CloseReason.ServerClosing);
- }
- #region Sending processing
-
-
-
-
-
- public virtual bool TrySend(string message)
- {
- var data = this.Charset.GetBytes(message);
- return InternalTrySend(new ArraySegment<byte>(data, 0, data.Length));
- }
-
-
-
-
- public virtual void Send(string message)
- {
- var data = this.Charset.GetBytes(message);
- Send(data, 0, data.Length);
- }
-
-
-
-
-
-
-
- public virtual bool TrySend(byte[] data, int offset, int length)
- {
- return InternalTrySend(new ArraySegment<byte>(data, offset, length));
- }
-
-
-
-
-
-
- public virtual void Send(byte[] data, int offset, int length)
- {
- InternalSend(new ArraySegment<byte>(data, offset, length));
- }
- private bool InternalTrySend(ArraySegment<byte> segment)
- {
- if (!SocketSession.TrySend(segment))
- return false;
- LastActiveTime = DateTime.Now;
- return true;
- }
-
-
-
-
-
- public virtual bool TrySend(ArraySegment<byte> segment)
- {
- if (!m_Connected)
- return false;
- return InternalTrySend(segment);
- }
- private void InternalSend(ArraySegment<byte> segment)
- {
- if (!m_Connected)
- return;
- if (InternalTrySend(segment))
- return;
- var sendTimeOut = Config.SendTimeOut;
-
- if (sendTimeOut < 0)
- {
- throw new TimeoutException("The sending attempt timed out");
- }
- var timeOutTime = sendTimeOut > 0 ? DateTime.Now.AddMilliseconds(sendTimeOut) : DateTime.Now;
- var spinWait = new SpinWait();
- while (m_Connected)
- {
- spinWait.SpinOnce();
- if (InternalTrySend(segment))
- return;
-
- if (sendTimeOut > 0 && DateTime.Now >= timeOutTime)
- {
- throw new TimeoutException("The sending attempt timed out");
- }
- }
- }
-
-
-
-
- public virtual void Send(ArraySegment<byte> segment)
- {
- InternalSend(segment);
- }
- private bool InternalTrySend(IList<ArraySegment<byte>> segments)
- {
- if (!SocketSession.TrySend(segments))
- return false;
- LastActiveTime = DateTime.Now;
- return true;
- }
-
-
-
-
-
- public virtual bool TrySend(IList<ArraySegment<byte>> segments)
- {
- if (!m_Connected)
- return false;
- return InternalTrySend(segments);
- }
- private void InternalSend(IList<ArraySegment<byte>> segments)
- {
- if (!m_Connected)
- return;
- if (InternalTrySend(segments))
- return;
- var sendTimeOut = Config.SendTimeOut;
-
- if (sendTimeOut < 0)
- {
- throw new TimeoutException("The sending attempt timed out");
- }
- var timeOutTime = sendTimeOut > 0 ? DateTime.Now.AddMilliseconds(sendTimeOut) : DateTime.Now;
- var spinWait = new SpinWait();
- while (m_Connected)
- {
- spinWait.SpinOnce();
- if (InternalTrySend(segments))
- return;
-
- if (sendTimeOut > 0 && DateTime.Now >= timeOutTime)
- {
- throw new TimeoutException("The sending attempt timed out");
- }
- }
- }
-
-
-
-
- public virtual void Send(IList<ArraySegment<byte>> segments)
- {
- InternalSend(segments);
- }
-
-
-
-
-
- public virtual void Send(string message, params object[] paramValues)
- {
- var data = this.Charset.GetBytes(string.Format(message, paramValues));
- InternalSend(new ArraySegment<byte>(data, 0, data.Length));
- }
- #endregion
- #region Receiving processing
-
-
-
-
- protected void SetNextReceiveFilter(IReceiveFilter<TRequestInfo> nextReceiveFilter)
- {
- m_ReceiveFilter = nextReceiveFilter;
- }
-
-
-
-
- protected virtual int GetMaxRequestLength()
- {
- return AppServer.Config.MaxRequestLength;
- }
-
-
-
-
-
-
-
-
-
-
- TRequestInfo FilterRequest(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest, out int offsetDelta)
- {
- if (!AppServer.OnRawDataReceived(this, readBuffer, offset, length))
- {
- rest = 0;
- offsetDelta = 0;
- return null;
- }
- var currentRequestLength = m_ReceiveFilter.LeftBufferSize;
- var requestInfo = m_ReceiveFilter.Filter(readBuffer, offset, length, toBeCopied, out rest);
- if (m_ReceiveFilter.State == FilterState.Error)
- {
- rest = 0;
- offsetDelta = 0;
- Close(CloseReason.ProtocolError);
- return null;
- }
- var offsetAdapter = m_ReceiveFilter as IOffsetAdapter;
- offsetDelta = offsetAdapter != null ? offsetAdapter.OffsetDelta : 0;
- if (requestInfo == null)
- {
-
- currentRequestLength = m_ReceiveFilter.LeftBufferSize;
- }
- else
- {
-
- currentRequestLength = currentRequestLength + length - rest;
- }
- var maxRequestLength = GetMaxRequestLength();
- if (currentRequestLength >= maxRequestLength)
- {
- if (Logger.IsErrorEnabled)
- Logger.Error(this, string.Format("Max request length: {0}, current processed length: {1}", maxRequestLength, currentRequestLength));
- Close(CloseReason.ProtocolError);
- return null;
- }
-
- if (m_ReceiveFilter.NextReceiveFilter != null)
- m_ReceiveFilter = m_ReceiveFilter.NextReceiveFilter;
- return requestInfo;
- }
-
-
-
-
-
-
-
-
-
-
- int IAppSession.ProcessRequest(byte[] readBuffer, int offset, int length, bool toBeCopied)
- {
- int rest, offsetDelta;
- while (true)
- {
- var requestInfo = FilterRequest(readBuffer, offset, length, toBeCopied, out rest, out offsetDelta);
- if (requestInfo != null)
- {
- try
- {
- AppServer.ExecuteCommand(this, requestInfo);
- }
- catch (Exception e)
- {
- HandleException(e);
- }
- }
- if (rest <= 0)
- {
- return offsetDelta;
- }
-
- offset = offset + length - rest;
- length = rest;
- }
- }
- #endregion
- }
-
-
-
-
- public abstract class AppSession<TAppSession> : AppSession<TAppSession, StringRequestInfo>
- where TAppSession : AppSession<TAppSession, StringRequestInfo>, IAppSession, new()
- {
- private bool m_AppendNewLineForResponse = false;
- private static string m_NewLine = "\r\n";
-
-
-
- public AppSession()
- : this(true)
- {
- }
-
-
-
-
- public AppSession(bool appendNewLineForResponse)
- {
- m_AppendNewLineForResponse = appendNewLineForResponse;
- }
-
-
-
-
- protected override void HandleUnknownRequest(StringRequestInfo requestInfo)
- {
- Send("Unknown request: " + requestInfo.Key);
- }
-
-
-
-
-
- protected virtual string ProcessSendingMessage(string rawMessage)
- {
- if (!m_AppendNewLineForResponse)
- return rawMessage;
- if (AppServer.Config.Mode == SocketMode.Udp)
- return rawMessage;
- if (string.IsNullOrEmpty(rawMessage) || !rawMessage.EndsWith(m_NewLine))
- return rawMessage + m_NewLine;
- else
- return rawMessage;
- }
-
-
-
-
-
- public override void Send(string message)
- {
- base.Send(ProcessSendingMessage(message));
- }
-
-
-
-
-
-
- public override void Send(string message, params object[] paramValues)
- {
- base.Send(ProcessSendingMessage(message), paramValues);
- }
- }
-
-
-
- public class AppSession : AppSession<AppSession>
- {
- }
- }
|