mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-11 18:48:36 -05:00
Add v2 of the Hosting Service and build nuget packages for it (#675)
* Port v2 of Hosting service to SqlToolsService - Renamed project to .v2 so that existing hosted service isn't impacted - Copied over the CoreServices project which contains ConnectionServiceCore and other reusable services for anything interacting with MSSQL - Ported unit test project across and verified tests run. * Nuget package support for reusable DLLs * Use 1.1 version per Karl's suggestion * Use correct license URL and project URL * Use new SMO packages
This commit is contained in:
59
src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs
Normal file
59
src/Microsoft.SqlTools.Hosting.v2/Protocol/MessageWriter.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
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.Instance.Write(LogLevel.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user