mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-15 17:23:32 -05:00
* Move unused forked code to external directory * Fix SLN build errors * Add back resource provider core since it's referenced by main resource provider project * Update PackageProjects step of pipeline
61 lines
2.3 KiB
C#
61 lines
2.3 KiB
C#
//
|
|
// Copyright (c) Microsoft. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
//
|
|
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.SqlTools.Hosting.Utility;
|
|
|
|
namespace Microsoft.SqlTools.Hosting.Protocol
|
|
{
|
|
public class MessageWriter
|
|
{
|
|
private const string ContentLength = "Content-Length: ";
|
|
private const string ContentType = "Content-Type: application/json";
|
|
private const string HeaderSeparator = "\r\n";
|
|
private const string HeaderEnd = "\r\n\r\n";
|
|
|
|
private readonly Stream outputStream;
|
|
private readonly AsyncLock writeLock = new AsyncLock();
|
|
|
|
public MessageWriter(Stream outputStream)
|
|
{
|
|
Validate.IsNotNull("streamWriter", outputStream);
|
|
|
|
this.outputStream = outputStream;
|
|
}
|
|
|
|
public virtual async Task WriteMessage(Message messageToWrite)
|
|
{
|
|
Validate.IsNotNull("messageToWrite", messageToWrite);
|
|
|
|
// Log the JSON representation of the message
|
|
string logMessage = string.Format("Sending message of type[{0}] and method[{1}]",
|
|
messageToWrite.MessageType, messageToWrite.Method);
|
|
Logger.Write(TraceEventType.Verbose, logMessage);
|
|
|
|
string serializedMessage = messageToWrite.Serialize();
|
|
// TODO: Allow encoding to be passed in
|
|
byte[] messageBytes = Encoding.UTF8.GetBytes(serializedMessage);
|
|
|
|
string headers = ContentLength + messageBytes.Length + HeaderSeparator
|
|
+ ContentType + HeaderEnd;
|
|
byte[] headerBytes = Encoding.ASCII.GetBytes(headers);
|
|
|
|
// Make sure only one call is writing at a time. You might be thinking
|
|
// "Why not use a normal lock?" We use an AsyncLock here so that the
|
|
// message loop doesn't get blocked while waiting for I/O to complete.
|
|
using (await writeLock.LockAsync())
|
|
{
|
|
// Send the message
|
|
await outputStream.WriteAsync(headerBytes, 0, headerBytes.Length);
|
|
await outputStream.WriteAsync(messageBytes, 0, messageBytes.Length);
|
|
await outputStream.FlushAsync();
|
|
}
|
|
}
|
|
}
|
|
}
|