public bool SetReceiver(Receiver receiver) { Receiver original = Interlocked.CompareExchange(ref _receiver, receiver, null); if (original != null) { return false; } else { return true; } }
public Session(SessionManager sessionContainer, string sessionId, Receiver receiver, SockJSOptions options) { _clientLock = new ReaderWriterLockSlim(); _sessionManager = sessionContainer; _sessionId = sessionId; _options = options; _receiver = receiver; _sendState = SendOpen; _receiveState = ReceiveNone; _receives = new ConcurrentQueue<PendingReceive>(); _receivesSem = new SemaphoreSlim(0); _sendDequeueSem = new SemaphoreSlim(1); _sendsSem = new SemaphoreSlim(0); _sendEnqueueSem = new SemaphoreSlim(1); _sends = new ConcurrentQueue<PendingSend>(); }
private async Task HandleReceiverAsync(string sessionId, Receiver receiver) { var getOrCreate = GetOrCreateSession(sessionId, receiver); Session session = getOrCreate.Item1; bool newSession = getOrCreate.Item2; if (newSession) { TaskCompletionSource<bool> acceptCompletionSource = new TaskCompletionSource<bool>(); var feature = new SessionWebSocketFeature(acceptCompletionSource, session); receiver.Context.Features.Set<IHttpWebSocketFeature>(feature); receiver.Context.Request.Path = _rewritePath; var wsHandler = Task.Factory.StartNew(async () => { try { await _next(receiver.Context); acceptCompletionSource.TrySetResult(false); } catch { acceptCompletionSource.TrySetResult(false); } }); bool accepted = await acceptCompletionSource.Task; if (!accepted) { _sessions.TryRemove(sessionId, out session); return; } } else { bool receiverSet = session.SetReceiver(receiver); if (receiverSet) { session.CancelSessionTimeout(); } session.ExitSharedLock(); if (!receiverSet) { await receiver.OpenAsync(); await receiver.SendCloseAsync(s_otherReceiverCloseMessage, CancellationToken.None); return; } } try { await session.ClientReceiveAsync(); } finally { // schedule before clear to ensure cancel is possible when receiverSet session.ScheduleSessionTimeout(session, OnSessionTimeout, _options.DisconnectTimeout); session.ClearReceiver(); } }
private Tuple<Session, bool> GetOrCreateSession(string sessionId, Receiver receiver) { while (true) { Session session = GetSession(sessionId); if (session != null) { return Tuple.Create(session, false); } Session newSession = new Session(this, sessionId, receiver, _options); Session check = _sessions.GetOrAdd(sessionId, newSession); if (check == newSession) { return Tuple.Create(newSession, true); } } }
private Task HandleXhrAsync(HttpContext context, string sessionId) { AddSessionCookie(context); AddNoCacheHeader(context); AddCorsHeader(context); var receiver = new Receiver(context, ReceiverType.XhrPolling, _options.MaxResponseLength, null); return HandleReceiverAsync(sessionId, receiver); }
private Task HandleHtmlFileAsync(HttpContext context, string sessionId) { AddSessionCookie(context); AddNoCacheHeader(context); AddCorsHeader(context); var query = context.Request.Query; var htmlFileCallback = (string)query["c"] ?? (string)query["callback"]; if (htmlFileCallback == null) { context.Response.StatusCode = StatusCodes.Status500InternalServerError; return context.Response.WriteAsync("\"callback\" parameter required"); } if (s_htmlFileCallbackRegex.IsMatch(htmlFileCallback)) { context.Response.StatusCode = StatusCodes.Status500InternalServerError; return context.Response.WriteAsync("invalid \"callback\" parameter"); } var receiver = new Receiver(context, ReceiverType.HtmlFile, _options.MaxResponseLength, htmlFileCallback); return HandleReceiverAsync(sessionId, receiver); }