Bug 1121804 - Add websocket message listener. r=dglastonbury

1. Fix websocket listener, and implement a light-wight parser.
2. Handle the messages from clients by protobuf
3. Handle disconnection while receiving the close message.
This commit is contained in:
Boris Chiou 2015-01-29 20:02:00 +01:00
parent d800fbc91b
commit 71a5472876
4 changed files with 854 additions and 178 deletions

View File

@ -10,9 +10,11 @@
#include "nsAppRunner.h"
#include "Composer2D.h"
#include "Effects.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Preferences.h"
#include "mozilla/Endian.h"
#include "mozilla/MathAlgorithms.h"
#include "mozilla/Preferences.h"
#include "mozilla/TimeStamp.h"
#include "TexturePoolOGL.h"
#include "mozilla/layers/CompositorOGL.h"
#include "mozilla/layers/CompositorParent.h"
@ -66,7 +68,8 @@ using namespace layerscope;
class DebugDataSender;
class DebugGLData;
/* This class handle websocket protocol which included
/*
* This class handle websocket protocol which included
* handshake and data frame's header
*/
class LayerScopeWebSocketHandler : public nsIInputStreamCallback {
@ -81,203 +84,48 @@ public:
LayerScopeWebSocketHandler()
: mState(NoHandshake)
, mConnected(false)
{ }
private:
virtual ~LayerScopeWebSocketHandler()
{
if (mTransport) {
mTransport->Close(NS_OK);
}
}
void OpenStream(nsISocketTransport* aTransport);
public:
void OpenStream(nsISocketTransport* aTransport) {
MOZ_ASSERT(aTransport);
mTransport = aTransport;
mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
0,
0,
getter_AddRefs(mOutputStream));
nsCOMPtr<nsIInputStream> debugInputStream;
mTransport->OpenInputStream(0,
0,
0,
getter_AddRefs(debugInputStream));
mInputStream = do_QueryInterface(debugInputStream);
mInputStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
}
bool WriteToStream(void *ptr, uint32_t size) {
if (mState == NoHandshake) {
// Not yet handshake, just return true in case of
// LayerScope remove this handle
return true;
} else if (mState == HandshakeFailed) {
return false;
}
// Generate WebSocket header
uint8_t wsHeader[10];
int wsHeaderSize = 0;
const uint8_t opcode = 0x2;
wsHeader[0] = 0x80 | (opcode & 0x0f); // FIN + opcode;
if (size <= 125) {
wsHeaderSize = 2;
wsHeader[1] = size;
} else if (size < 65536) {
wsHeaderSize = 4;
wsHeader[1] = 0x7E;
NetworkEndian::writeUint16(wsHeader + 2, size);
} else {
wsHeaderSize = 10;
wsHeader[1] = 0x7F;
NetworkEndian::writeUint64(wsHeader + 2, size);
}
// Send WebSocket header
nsresult rv;
uint32_t cnt;
rv = mOutputStream->Write(reinterpret_cast<char*>(wsHeader),
wsHeaderSize, &cnt);
if (NS_FAILED(rv))
return false;
uint32_t written = 0;
while (written < size) {
uint32_t cnt;
rv = mOutputStream->Write(reinterpret_cast<char*>(ptr) + written,
size - written, &cnt);
if (NS_FAILED(rv))
return false;
written += cnt;
}
return true;
}
bool WriteToStream(void *aPtr, uint32_t aSize);
// nsIInputStreamCallback
NS_IMETHODIMP OnInputStreamReady(nsIAsyncInputStream *stream) MOZ_OVERRIDE
{
nsTArray<nsCString> protocolString;
ReadInputStreamData(protocolString);
NS_IMETHODIMP OnInputStreamReady(nsIAsyncInputStream *aStream) MOZ_OVERRIDE;
if (WebSocketHandshake(protocolString)) {
mState = HandshakeSuccess;
} else {
mState = HandshakeFailed;
}
return NS_OK;
}
private:
void ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
{
nsLineBuffer<char> lineBuffer;
nsCString line;
bool more = true;
do {
NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more);
virtual ~LayerScopeWebSocketHandler() { CloseConnection(); }
if (line.Length() > 0) {
aProtocolString.AppendElement(line);
}
} while (more && line.Length() > 0);
}
void ReadInputStreamData(nsTArray<nsCString>& aProtocolString);
bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
{
nsresult rv;
bool isWebSocket = false;
nsCString version;
nsCString wsKey;
nsCString protocol;
bool WebSocketHandshake(nsTArray<nsCString>& aProtocolString);
// Validate WebSocket client request.
if (aProtocolString.Length() == 0)
return false;
nsresult HandleSocketMessage(nsIAsyncInputStream *aStream);
// Check that the HTTP method is GET
const char* HTTP_METHOD = "GET ";
if (strncmp(aProtocolString[0].get(), HTTP_METHOD, strlen(HTTP_METHOD)) != 0) {
return false;
}
nsresult ProcessInput(uint8_t *aBuffer, uint32_t aCount);
for (uint32_t i = 1; i < aProtocolString.Length(); ++i) {
const char* line = aProtocolString[i].get();
const char* prop_pos = strchr(line, ':');
if (prop_pos != nullptr) {
nsCString key(line, prop_pos - line);
nsCString value(prop_pos + 2);
if (key.EqualsIgnoreCase("upgrade") &&
value.EqualsIgnoreCase("websocket")) {
isWebSocket = true;
} else if (key.EqualsIgnoreCase("sec-websocket-version")) {
version = value;
} else if (key.EqualsIgnoreCase("sec-websocket-key")) {
wsKey = value;
} else if (key.EqualsIgnoreCase("sec-websocket-protocol")) {
protocol = value;
}
}
}
// Copied from WebsocketChannel, helper function to decode data frame
void ApplyMask(uint32_t aMask, uint8_t *aData, uint64_t aLen);
if (!isWebSocket) {
return false;
}
bool HandleDataFrame(uint8_t *aData, uint32_t aSize);
if (!(version.EqualsLiteral("7") ||
version.EqualsLiteral("8") ||
version.EqualsLiteral("13"))) {
return false;
}
if (!(protocol.EqualsIgnoreCase("binary"))) {
return false;
}
// Client request is valid. Start to generate and send server response.
nsAutoCString guid("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
nsAutoCString res;
SHA1Sum sha1;
nsCString combined(wsKey + guid);
sha1.update(combined.get(), combined.Length());
uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
sha1.finish(digest);
nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::kHashSize);
Base64Encode(newString, res);
nsCString response("HTTP/1.1 101 Switching Protocols\r\n");
response.AppendLiteral("Upgrade: websocket\r\n");
response.AppendLiteral("Connection: Upgrade\r\n");
response.Append(nsCString("Sec-WebSocket-Accept: ") + res + nsCString("\r\n"));
response.AppendLiteral("Sec-WebSocket-Protocol: binary\r\n\r\n");
uint32_t written = 0;
uint32_t size = response.Length();
while (written < size) {
uint32_t cnt;
rv = mOutputStream->Write(const_cast<char*>(response.get()) + written,
size - written, &cnt);
if (NS_FAILED(rv))
return false;
written += cnt;
}
mOutputStream->Flush();
return true;
}
void CloseConnection();
private:
nsCOMPtr<nsIOutputStream> mOutputStream;
nsCOMPtr<nsIAsyncInputStream> mInputStream;
nsCOMPtr<nsISocketTransport> mTransport;
SocketStateType mState;
bool mConnected;
};
NS_IMPL_ISUPPORTS(LayerScopeWebSocketHandler, nsIInputStreamCallback);
/*
* Manage Websocket connections
*/
class LayerScopeWebSocketManager {
public:
LayerScopeWebSocketManager();
@ -720,6 +568,12 @@ public:
int aWidth = 0,
int aHeight = 0);
static void SetLayersTreeSendable(bool aSet) {sLayersTreeSendable = aSet;}
static void SetLayersBufferSendable(bool aSet) {sLayersBufferSendable = aSet;}
static bool GetLayersTreeSendable() {return sLayersTreeSendable;}
// Sender private functions
private:
static void SendColor(void* aLayerRef,
@ -736,8 +590,16 @@ private:
static void SendYCbCrEffect(GLContext* aGLContext,
void* aLayerRef,
const EffectYCbCr* aEffect);
// Data fields
private:
static bool sLayersTreeSendable;
static bool sLayersBufferSendable;
};
bool SenderHelper::sLayersTreeSendable = true;
bool SenderHelper::sLayersBufferSendable = true;
// ----------------------------------------------
// SenderHelper implementation
@ -874,6 +736,8 @@ SenderHelper::SendEffectChain(GLContext* aGLContext,
int aWidth,
int aHeight)
{
if (!sLayersBufferSendable) return;
const Effect* primaryEffect = aEffectChain.mPrimaryEffect;
switch (primaryEffect->mType) {
case EffectTypes::RGB: {
@ -908,6 +772,430 @@ SenderHelper::SendEffectChain(GLContext* aGLContext,
// TODO:
}
// ----------------------------------------------
// LayerScopeWebSocketHandler implementation
// ----------------------------------------------
void
LayerScopeWebSocketHandler::OpenStream(nsISocketTransport* aTransport)
{
MOZ_ASSERT(aTransport);
mTransport = aTransport;
mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING,
0,
0,
getter_AddRefs(mOutputStream));
nsCOMPtr<nsIInputStream> debugInputStream;
mTransport->OpenInputStream(0,
0,
0,
getter_AddRefs(debugInputStream));
mInputStream = do_QueryInterface(debugInputStream);
mInputStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
}
bool
LayerScopeWebSocketHandler::WriteToStream(void *aPtr,
uint32_t aSize)
{
if (mState == NoHandshake) {
// Not yet handshake, just return true in case of
// LayerScope remove this handle
return true;
} else if (mState == HandshakeFailed) {
return false;
}
if (!mOutputStream) {
return false;
}
// Generate WebSocket header
uint8_t wsHeader[10];
int wsHeaderSize = 0;
const uint8_t opcode = 0x2;
wsHeader[0] = 0x80 | (opcode & 0x0f); // FIN + opcode;
if (aSize <= 125) {
wsHeaderSize = 2;
wsHeader[1] = aSize;
} else if (aSize < 65536) {
wsHeaderSize = 4;
wsHeader[1] = 0x7E;
NetworkEndian::writeUint16(wsHeader + 2, aSize);
} else {
wsHeaderSize = 10;
wsHeader[1] = 0x7F;
NetworkEndian::writeUint64(wsHeader + 2, aSize);
}
// Send WebSocket header
nsresult rv;
uint32_t cnt;
rv = mOutputStream->Write(reinterpret_cast<char*>(wsHeader),
wsHeaderSize, &cnt);
if (NS_FAILED(rv))
return false;
uint32_t written = 0;
while (written < aSize) {
uint32_t cnt;
rv = mOutputStream->Write(reinterpret_cast<char*>(aPtr) + written,
aSize - written, &cnt);
if (NS_FAILED(rv))
return false;
written += cnt;
}
return true;
}
NS_IMETHODIMP
LayerScopeWebSocketHandler::OnInputStreamReady(nsIAsyncInputStream *aStream)
{
MOZ_ASSERT(mInputStream);
if (!mInputStream) {
return NS_OK;
}
if (!mConnected) {
nsTArray<nsCString> protocolString;
ReadInputStreamData(protocolString);
if (WebSocketHandshake(protocolString)) {
mState = HandshakeSuccess;
mConnected = true;
mInputStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
} else {
mState = HandshakeFailed;
}
return NS_OK;
} else {
return HandleSocketMessage(aStream);
}
}
void
LayerScopeWebSocketHandler::ReadInputStreamData(nsTArray<nsCString>& aProtocolString)
{
nsLineBuffer<char> lineBuffer;
nsCString line;
bool more = true;
do {
NS_ReadLine(mInputStream.get(), &lineBuffer, line, &more);
if (line.Length() > 0) {
aProtocolString.AppendElement(line);
}
} while (more && line.Length() > 0);
}
bool
LayerScopeWebSocketHandler::WebSocketHandshake(nsTArray<nsCString>& aProtocolString)
{
nsresult rv;
bool isWebSocket = false;
nsCString version;
nsCString wsKey;
nsCString protocol;
// Validate WebSocket client request.
if (aProtocolString.Length() == 0)
return false;
// Check that the HTTP method is GET
const char* HTTP_METHOD = "GET ";
if (strncmp(aProtocolString[0].get(), HTTP_METHOD, strlen(HTTP_METHOD)) != 0) {
return false;
}
for (uint32_t i = 1; i < aProtocolString.Length(); ++i) {
const char* line = aProtocolString[i].get();
const char* prop_pos = strchr(line, ':');
if (prop_pos != nullptr) {
nsCString key(line, prop_pos - line);
nsCString value(prop_pos + 2);
if (key.EqualsIgnoreCase("upgrade") &&
value.EqualsIgnoreCase("websocket")) {
isWebSocket = true;
} else if (key.EqualsIgnoreCase("sec-websocket-version")) {
version = value;
} else if (key.EqualsIgnoreCase("sec-websocket-key")) {
wsKey = value;
} else if (key.EqualsIgnoreCase("sec-websocket-protocol")) {
protocol = value;
}
}
}
if (!isWebSocket) {
return false;
}
if (!(version.EqualsLiteral("7") ||
version.EqualsLiteral("8") ||
version.EqualsLiteral("13"))) {
return false;
}
if (!(protocol.EqualsIgnoreCase("binary"))) {
return false;
}
if (!mOutputStream) {
return false;
}
// Client request is valid. Start to generate and send server response.
nsAutoCString guid("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
nsAutoCString res;
SHA1Sum sha1;
nsCString combined(wsKey + guid);
sha1.update(combined.get(), combined.Length());
uint8_t digest[SHA1Sum::kHashSize]; // SHA1 digests are 20 bytes long.
sha1.finish(digest);
nsCString newString(reinterpret_cast<char*>(digest), SHA1Sum::kHashSize);
Base64Encode(newString, res);
nsCString response("HTTP/1.1 101 Switching Protocols\r\n");
response.AppendLiteral("Upgrade: websocket\r\n");
response.AppendLiteral("Connection: Upgrade\r\n");
response.Append(nsCString("Sec-WebSocket-Accept: ") + res + nsCString("\r\n"));
response.AppendLiteral("Sec-WebSocket-Protocol: binary\r\n\r\n");
uint32_t written = 0;
uint32_t size = response.Length();
while (written < size) {
uint32_t cnt;
rv = mOutputStream->Write(const_cast<char*>(response.get()) + written,
size - written, &cnt);
if (NS_FAILED(rv))
return false;
written += cnt;
}
mOutputStream->Flush();
return true;
}
nsresult
LayerScopeWebSocketHandler::HandleSocketMessage(nsIAsyncInputStream *aStream)
{
// The reading and parsing of this input stream is customized for layer viewer.
const uint32_t cPacketSize = 1024;
char buffer[cPacketSize];
uint32_t count = 0;
nsresult rv = NS_OK;
do {
rv = mInputStream->Read((char *)buffer, cPacketSize, &count);
// TODO: combine packets if we have to read more than once
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
mInputStream->AsyncWait(this, 0, 0, NS_GetCurrentThread());
return NS_OK;
}
if (NS_FAILED(rv)) {
break;
}
if (count == 0) {
// NS_BASE_STREAM_CLOSED
CloseConnection();
break;
}
rv = ProcessInput(reinterpret_cast<uint8_t *>(buffer), count);
} while (NS_SUCCEEDED(rv) && mInputStream);
return rv;
}
nsresult
LayerScopeWebSocketHandler::ProcessInput(uint8_t *aBuffer,
uint32_t aCount)
{
uint32_t avail = aCount;
// Decode Websocket data frame
if (avail <= 2) {
NS_WARNING("Packet size is less than 2 bytes");
return NS_OK;
}
// First byte, data type, only care the opcode
// rsvBits: aBuffer[0] & 0x70 (0111 0000)
uint8_t finBit = aBuffer[0] & 0x80; // 1000 0000
uint8_t opcode = aBuffer[0] & 0x0F; // 0000 1111
if (!finBit) {
NS_WARNING("We cannot handle multi-fragments messages in Layerscope websocket parser.");
return NS_OK;
}
// Second byte, data length
uint8_t maskBit = aBuffer[1] & 0x80; // 1000 0000
int64_t payloadLength64 = aBuffer[1] & 0x7F; // 0111 1111
if (!maskBit) {
NS_WARNING("Client to Server should set the mask bit");
return NS_OK;
}
uint32_t framingLength = 2 + 4; // 4 for masks
if (payloadLength64 < 126) {
if (avail < framingLength)
return NS_OK;
} else if (payloadLength64 == 126) {
// 16 bit length field
framingLength += 2;
if (avail < framingLength) {
return NS_OK;
}
payloadLength64 = aBuffer[2] << 8 | aBuffer[3];
} else {
// 64 bit length
framingLength += 8;
if (avail < framingLength) {
return NS_OK;
}
if (aBuffer[2] & 0x80) {
// Section 4.2 says that the most significant bit MUST be
// 0. (i.e. this is really a 63 bit value)
NS_WARNING("High bit of 64 bit length set");
return NS_ERROR_ILLEGAL_VALUE;
}
// copy this in case it is unaligned
payloadLength64 = NetworkEndian::readInt64(aBuffer + 2);
}
uint8_t *payload = aBuffer + framingLength;
avail -= framingLength;
uint32_t payloadLength = static_cast<uint32_t>(payloadLength64);
if (avail < payloadLength) {
NS_WARNING("Packet size mismatch the payload length");
return NS_OK;
}
// Apply mask
uint32_t mask = NetworkEndian::readUint32(payload - 4);
ApplyMask(mask, payload, payloadLength);
if (opcode == 0x8) {
// opcode == 0x8 means connection close
CloseConnection();
return NS_BASE_STREAM_CLOSED;
}
if (!HandleDataFrame(payload, payloadLength)) {
NS_WARNING("Cannot decode payload data by the protocol buffer");
}
return NS_OK;
}
void
LayerScopeWebSocketHandler::ApplyMask(uint32_t aMask,
uint8_t *aData,
uint64_t aLen)
{
if (!aData || aLen == 0) {
return;
}
// Optimally we want to apply the mask 32 bits at a time,
// but the buffer might not be alligned. So we first deal with
// 0 to 3 bytes of preamble individually
while (aLen && (reinterpret_cast<uintptr_t>(aData) & 3)) {
*aData ^= aMask >> 24;
aMask = RotateLeft(aMask, 8);
aData++;
aLen--;
}
// perform mask on full words of data
uint32_t *iData = reinterpret_cast<uint32_t *>(aData);
uint32_t *end = iData + (aLen >> 2);
NetworkEndian::writeUint32(&aMask, aMask);
for (; iData < end; iData++) {
*iData ^= aMask;
}
aMask = NetworkEndian::readUint32(&aMask);
aData = (uint8_t *)iData;
aLen = aLen % 4;
// There maybe up to 3 trailing bytes that need to be dealt with
// individually
while (aLen) {
*aData ^= aMask >> 24;
aMask = RotateLeft(aMask, 8);
aData++;
aLen--;
}
}
bool
LayerScopeWebSocketHandler::HandleDataFrame(uint8_t *aData,
uint32_t aSize)
{
// Handle payload data by protocol buffer
auto p = MakeUnique<CommandPacket>();
p->ParseFromArray(static_cast<void*>(aData), aSize);
if (!p->has_type()) {
MOZ_ASSERT(false, "Protocol buffer decoding failed or cannot recongize it");
return false;
}
switch (p->type()) {
case CommandPacket::LAYERS_TREE:
if (p->has_value()) {
SenderHelper::SetLayersTreeSendable(p->value());
}
break;
case CommandPacket::LAYERS_BUFFER:
if (p->has_value()) {
SenderHelper::SetLayersBufferSendable(p->value());
}
break;
case CommandPacket::NO_OP:
default:
NS_WARNING("Invalid message type");
break;
}
return true;
}
void
LayerScopeWebSocketHandler::CloseConnection()
{
WebSocketHelper::GetSocketManager()->CleanDebugData();
if (mInputStream) {
mInputStream->AsyncWait(nullptr, 0, 0, nullptr);
mInputStream = nullptr;
}
if (mOutputStream) {
mOutputStream = nullptr;
}
if (mTransport) {
mTransport->Close(NS_BASE_STREAM_CLOSED);
mTransport = nullptr;
}
mConnected = false;
}
// ----------------------------------------------
// LayerScopeWebSocketManager implementation
// ----------------------------------------------
@ -923,6 +1211,7 @@ LayerScopeWebSocketManager::LayerScopeWebSocketManager()
LayerScopeWebSocketManager::~LayerScopeWebSocketManager()
{
mServerSocket->Close();
}
void
@ -1005,7 +1294,7 @@ void
LayerScope::SendLayerDump(UniquePtr<Packet> aPacket)
{
// Protect this public function
if (!CheckSendable()) {
if (!CheckSendable() || !SenderHelper::GetLayersTreeSendable()) {
return;
}
WebSocketHelper::GetSocketManager()->AppendDebugData(

View File

@ -27,6 +27,7 @@ void protobuf_ShutdownFile_LayerScopePacket_2eproto() {
delete LayersPacket_Layer_Shadow::default_instance_;
delete MetaPacket::default_instance_;
delete Packet::default_instance_;
delete CommandPacket::default_instance_;
}
void protobuf_AddDesc_LayerScopePacket_2eproto() {
@ -47,6 +48,7 @@ void protobuf_AddDesc_LayerScopePacket_2eproto() {
LayersPacket_Layer_Shadow::default_instance_ = new LayersPacket_Layer_Shadow();
MetaPacket::default_instance_ = new MetaPacket();
Packet::default_instance_ = new Packet();
CommandPacket::default_instance_ = new CommandPacket();
FramePacket::default_instance_->InitAsDefaultInstance();
ColorPacket::default_instance_->InitAsDefaultInstance();
TexturePacket::default_instance_->InitAsDefaultInstance();
@ -59,6 +61,7 @@ void protobuf_AddDesc_LayerScopePacket_2eproto() {
LayersPacket_Layer_Shadow::default_instance_->InitAsDefaultInstance();
MetaPacket::default_instance_->InitAsDefaultInstance();
Packet::default_instance_->InitAsDefaultInstance();
CommandPacket::default_instance_->InitAsDefaultInstance();
::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_LayerScopePacket_2eproto);
}
@ -3573,6 +3576,220 @@ void Packet::Swap(Packet* other) {
}
// ===================================================================
bool CommandPacket_CmdType_IsValid(int value) {
switch(value) {
case 0:
case 1:
case 2:
return true;
default:
return false;
}
}
#ifndef _MSC_VER
const CommandPacket_CmdType CommandPacket::NO_OP;
const CommandPacket_CmdType CommandPacket::LAYERS_TREE;
const CommandPacket_CmdType CommandPacket::LAYERS_BUFFER;
const CommandPacket_CmdType CommandPacket::CmdType_MIN;
const CommandPacket_CmdType CommandPacket::CmdType_MAX;
const int CommandPacket::CmdType_ARRAYSIZE;
#endif // _MSC_VER
#ifndef _MSC_VER
const int CommandPacket::kTypeFieldNumber;
const int CommandPacket::kValueFieldNumber;
#endif // !_MSC_VER
CommandPacket::CommandPacket()
: ::google::protobuf::MessageLite() {
SharedCtor();
}
void CommandPacket::InitAsDefaultInstance() {
}
CommandPacket::CommandPacket(const CommandPacket& from)
: ::google::protobuf::MessageLite() {
SharedCtor();
MergeFrom(from);
}
void CommandPacket::SharedCtor() {
_cached_size_ = 0;
type_ = 0;
value_ = false;
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
CommandPacket::~CommandPacket() {
SharedDtor();
}
void CommandPacket::SharedDtor() {
if (this != default_instance_) {
}
}
void CommandPacket::SetCachedSize(int size) const {
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
}
const CommandPacket& CommandPacket::default_instance() {
if (default_instance_ == NULL) protobuf_AddDesc_LayerScopePacket_2eproto(); return *default_instance_;
}
CommandPacket* CommandPacket::default_instance_ = NULL;
CommandPacket* CommandPacket::New() const {
return new CommandPacket;
}
void CommandPacket::Clear() {
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
type_ = 0;
value_ = false;
}
::memset(_has_bits_, 0, sizeof(_has_bits_));
}
bool CommandPacket::MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input) {
#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
::google::protobuf::uint32 tag;
while ((tag = input->ReadTag()) != 0) {
switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// required .mozilla.layers.layerscope.CommandPacket.CmdType type = 1;
case 1: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
int value;
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>(
input, &value)));
if (::mozilla::layers::layerscope::CommandPacket_CmdType_IsValid(value)) {
set_type(static_cast< ::mozilla::layers::layerscope::CommandPacket_CmdType >(value));
}
} else {
goto handle_uninterpreted;
}
if (input->ExpectTag(16)) goto parse_value;
break;
}
// optional bool value = 2;
case 2: {
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
parse_value:
DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
input, &value_)));
set_has_value();
} else {
goto handle_uninterpreted;
}
if (input->ExpectAtEnd()) return true;
break;
}
default: {
handle_uninterpreted:
if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
return true;
}
DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));
break;
}
}
}
return true;
#undef DO_
}
void CommandPacket::SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const {
// required .mozilla.layers.layerscope.CommandPacket.CmdType type = 1;
if (has_type()) {
::google::protobuf::internal::WireFormatLite::WriteEnum(
1, this->type(), output);
}
// optional bool value = 2;
if (has_value()) {
::google::protobuf::internal::WireFormatLite::WriteBool(2, this->value(), output);
}
}
int CommandPacket::ByteSize() const {
int total_size = 0;
if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
// required .mozilla.layers.layerscope.CommandPacket.CmdType type = 1;
if (has_type()) {
total_size += 1 +
::google::protobuf::internal::WireFormatLite::EnumSize(this->type());
}
// optional bool value = 2;
if (has_value()) {
total_size += 1 + 1;
}
}
GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();
_cached_size_ = total_size;
GOOGLE_SAFE_CONCURRENT_WRITES_END();
return total_size;
}
void CommandPacket::CheckTypeAndMergeFrom(
const ::google::protobuf::MessageLite& from) {
MergeFrom(*::google::protobuf::down_cast<const CommandPacket*>(&from));
}
void CommandPacket::MergeFrom(const CommandPacket& from) {
GOOGLE_CHECK_NE(&from, this);
if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
if (from.has_type()) {
set_type(from.type());
}
if (from.has_value()) {
set_value(from.value());
}
}
}
void CommandPacket::CopyFrom(const CommandPacket& from) {
if (&from == this) return;
Clear();
MergeFrom(from);
}
bool CommandPacket::IsInitialized() const {
if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
return true;
}
void CommandPacket::Swap(CommandPacket* other) {
if (other != this) {
std::swap(type_, other->type_);
std::swap(value_, other->value_);
std::swap(_has_bits_[0], other->_has_bits_[0]);
std::swap(_cached_size_, other->_cached_size_);
}
}
::std::string CommandPacket::GetTypeName() const {
return "mozilla.layers.layerscope.CommandPacket";
}
// @@protoc_insertion_point(namespace_scope)
} // namespace layerscope

View File

@ -45,6 +45,7 @@ class LayersPacket_Layer_Matrix;
class LayersPacket_Layer_Shadow;
class MetaPacket;
class Packet;
class CommandPacket;
enum LayersPacket_Layer_LayerType {
LayersPacket_Layer_LayerType_UnknownLayer = 0,
@ -98,6 +99,16 @@ const Packet_DataType Packet_DataType_DataType_MIN = Packet_DataType_FRAMESTART;
const Packet_DataType Packet_DataType_DataType_MAX = Packet_DataType_META;
const int Packet_DataType_DataType_ARRAYSIZE = Packet_DataType_DataType_MAX + 1;
enum CommandPacket_CmdType {
CommandPacket_CmdType_NO_OP = 0,
CommandPacket_CmdType_LAYERS_TREE = 1,
CommandPacket_CmdType_LAYERS_BUFFER = 2
};
bool CommandPacket_CmdType_IsValid(int value);
const CommandPacket_CmdType CommandPacket_CmdType_CmdType_MIN = CommandPacket_CmdType_NO_OP;
const CommandPacket_CmdType CommandPacket_CmdType_CmdType_MAX = CommandPacket_CmdType_LAYERS_BUFFER;
const int CommandPacket_CmdType_CmdType_ARRAYSIZE = CommandPacket_CmdType_CmdType_MAX + 1;
// ===================================================================
class FramePacket : public ::google::protobuf::MessageLite {
@ -1439,6 +1450,99 @@ class Packet : public ::google::protobuf::MessageLite {
void InitAsDefaultInstance();
static Packet* default_instance_;
};
// -------------------------------------------------------------------
class CommandPacket : public ::google::protobuf::MessageLite {
public:
CommandPacket();
virtual ~CommandPacket();
CommandPacket(const CommandPacket& from);
inline CommandPacket& operator=(const CommandPacket& from) {
CopyFrom(from);
return *this;
}
static const CommandPacket& default_instance();
void Swap(CommandPacket* other);
// implements Message ----------------------------------------------
CommandPacket* New() const;
void CheckTypeAndMergeFrom(const ::google::protobuf::MessageLite& from);
void CopyFrom(const CommandPacket& from);
void MergeFrom(const CommandPacket& from);
void Clear();
bool IsInitialized() const;
int ByteSize() const;
bool MergePartialFromCodedStream(
::google::protobuf::io::CodedInputStream* input);
void SerializeWithCachedSizes(
::google::protobuf::io::CodedOutputStream* output) const;
int GetCachedSize() const { return _cached_size_; }
private:
void SharedCtor();
void SharedDtor();
void SetCachedSize(int size) const;
public:
::std::string GetTypeName() const;
// nested types ----------------------------------------------------
typedef CommandPacket_CmdType CmdType;
static const CmdType NO_OP = CommandPacket_CmdType_NO_OP;
static const CmdType LAYERS_TREE = CommandPacket_CmdType_LAYERS_TREE;
static const CmdType LAYERS_BUFFER = CommandPacket_CmdType_LAYERS_BUFFER;
static inline bool CmdType_IsValid(int value) {
return CommandPacket_CmdType_IsValid(value);
}
static const CmdType CmdType_MIN =
CommandPacket_CmdType_CmdType_MIN;
static const CmdType CmdType_MAX =
CommandPacket_CmdType_CmdType_MAX;
static const int CmdType_ARRAYSIZE =
CommandPacket_CmdType_CmdType_ARRAYSIZE;
// accessors -------------------------------------------------------
// required .mozilla.layers.layerscope.CommandPacket.CmdType type = 1;
inline bool has_type() const;
inline void clear_type();
static const int kTypeFieldNumber = 1;
inline ::mozilla::layers::layerscope::CommandPacket_CmdType type() const;
inline void set_type(::mozilla::layers::layerscope::CommandPacket_CmdType value);
// optional bool value = 2;
inline bool has_value() const;
inline void clear_value();
static const int kValueFieldNumber = 2;
inline bool value() const;
inline void set_value(bool value);
// @@protoc_insertion_point(class_scope:mozilla.layers.layerscope.CommandPacket)
private:
inline void set_has_type();
inline void clear_has_type();
inline void set_has_value();
inline void clear_has_value();
int type_;
bool value_;
mutable int _cached_size_;
::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
friend void protobuf_AddDesc_LayerScopePacket_2eproto();
friend void protobuf_AssignDesc_LayerScopePacket_2eproto();
friend void protobuf_ShutdownFile_LayerScopePacket_2eproto();
void InitAsDefaultInstance();
static CommandPacket* default_instance_;
};
// ===================================================================
@ -2803,6 +2907,55 @@ inline ::mozilla::layers::layerscope::MetaPacket* Packet::release_meta() {
return temp;
}
// -------------------------------------------------------------------
// CommandPacket
// required .mozilla.layers.layerscope.CommandPacket.CmdType type = 1;
inline bool CommandPacket::has_type() const {
return (_has_bits_[0] & 0x00000001u) != 0;
}
inline void CommandPacket::set_has_type() {
_has_bits_[0] |= 0x00000001u;
}
inline void CommandPacket::clear_has_type() {
_has_bits_[0] &= ~0x00000001u;
}
inline void CommandPacket::clear_type() {
type_ = 0;
clear_has_type();
}
inline ::mozilla::layers::layerscope::CommandPacket_CmdType CommandPacket::type() const {
return static_cast< ::mozilla::layers::layerscope::CommandPacket_CmdType >(type_);
}
inline void CommandPacket::set_type(::mozilla::layers::layerscope::CommandPacket_CmdType value) {
GOOGLE_DCHECK(::mozilla::layers::layerscope::CommandPacket_CmdType_IsValid(value));
set_has_type();
type_ = value;
}
// optional bool value = 2;
inline bool CommandPacket::has_value() const {
return (_has_bits_[0] & 0x00000002u) != 0;
}
inline void CommandPacket::set_has_value() {
_has_bits_[0] |= 0x00000002u;
}
inline void CommandPacket::clear_has_value() {
_has_bits_[0] &= ~0x00000002u;
}
inline void CommandPacket::clear_value() {
value_ = false;
clear_has_value();
}
inline bool CommandPacket::value() const {
return value_;
}
inline void CommandPacket::set_value(bool value) {
set_has_value();
value_ = value;
}
// @@protoc_insertion_point(namespace_scope)

View File

@ -4,6 +4,9 @@ option optimize_for = LITE_RUNTIME;
package mozilla.layers.layerscope;
// ===============================
// Server to Client messages
// ===============================
message FramePacket {
optional uint64 value = 1;
}
@ -133,3 +136,17 @@ message Packet {
optional LayersPacket layers = 5;
optional MetaPacket meta = 6;
}
// ===============================
// Client to Server messages
// ===============================
message CommandPacket {
enum CmdType {
NO_OP = 0;
LAYERS_TREE = 1;
LAYERS_BUFFER = 2;
}
required CmdType type = 1;
optional bool value = 2;
}