/// <summary> /// Send application data to the connected endpoint /// </summary> /// <remarks>This method is blocking</remarks> /// <param name="payload"></param> public Response Send(byte[] payload) { var id = _messageIdProvider.Next(); try { // disallow sending if the session is not in the open state if (State != SessionState.Open) { throw new SessionException(); } // create message with next message ID - do not add the payload to the message as message is just for tracking var message = new Message(this, id, null); // add to the message pending settlement collection - will be accessed async lock (_pendingMessages) { _pendingMessages.Add(message.ID, message); } // pass the message down to the connection for transmission Connection.SendMessage(ID, message.ID, payload); // wait for the message to be settled or time out if (!message.Settled.WaitOne(60000)) { throw new MessageTimeoutException(); } // return the response return(new Response(message.Accepted, message.ResponseData)); } finally { lock (_pendingMessages) { _pendingMessages.Remove(id); } _messageIdProvider.Remove(id); } }
/// <summary> /// Creates a new session between both endpoints /// </summary> /// <param name="name">The application-defined name for the session</param> /// <param name="data">Optional payload data to be sent to the remote endpoint</param> /// <returns>The created session</returns> public Session CreateSession(string name, byte[] data = null) { if (State != ConnectionState.Open) { throw new ConnectionException(); } uint id = uint.MaxValue; try { // create the session descriptor which is sent to the remote endpoint var descriptor = new SessionDescriptor { Name = name, Data = data }; // construct new session frame Session session; lock (_pendingSessions) { id = _sessionIdProvider.Next(); session = new Session(this, descriptor, id); _pendingSessions.Add(session.ID, session); } // send the session start frame _sendFrame(FrameType.SessionStart, Frame.CreateSessionStartFrame(session.ID, BsonCodec.Encode(descriptor))); // block until the connection is settled or a timeout occurs var index = WaitHandle.WaitAny(new[] { session.Settled, session.SessionError }, 5000); switch (index) { // session was settled (application needs to check if it was accepted/rejected case 0: return(session); // the session was rejected by the remote endpoint case 1: throw new SessionRejectedException($"The session was rejected by the remote endpoint"); // the session creation timedout case WaitHandle.WaitTimeout: throw new SessionTimeoutException($"Session settlement timed out after {5000} ms"); // should never hit here, but have to return something default: throw new Exception(); } } catch (Exception) { lock (_pendingSessions) { if (_pendingSessions.ContainsKey(id)) { _pendingSessions.Remove(id); } _sessionIdProvider.Remove(id); } throw; } }