summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/amqp/Sasl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/qpid/amqp/Sasl.cpp')
-rw-r--r--cpp/src/qpid/amqp/Sasl.cpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/cpp/src/qpid/amqp/Sasl.cpp b/cpp/src/qpid/amqp/Sasl.cpp
new file mode 100644
index 0000000000..7b0779fe94
--- /dev/null
+++ b/cpp/src/qpid/amqp/Sasl.cpp
@@ -0,0 +1,136 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "qpid/amqp/Sasl.h"
+#include "qpid/amqp/Decoder.h"
+#include "qpid/amqp/Descriptor.h"
+#include "qpid/amqp/Encoder.h"
+#include "qpid/log/Statement.h"
+#include "qpid/framing/Buffer.h"
+#include "qpid/framing/ProtocolVersion.h"
+#include "qpid/framing/ProtocolInitiation.h"
+#include <string.h>
+
+namespace qpid {
+namespace amqp {
+
+Sasl::Sasl(const std::string& i) : id(i), buffer(2*512/*AMQP 1.0's MAX_MIN_FRAME_SIZE - is this enough though?*/), encoder(&buffer[0], buffer.size()) {}
+Sasl::~Sasl() {}
+
+void* Sasl::startFrame()
+{
+ //write sasl frame header, leaving 4 bytes for total size
+ char* start = encoder.skip(4);
+ encoder.write((uint8_t) 0x02);//data offset
+ encoder.write((uint8_t) 0x01);//frame type
+ encoder.write((uint16_t) 0x0000);//ignored
+ return start;
+}
+
+void Sasl::endFrame(void* frame)
+{
+ //now backfill the frame size
+ char* start = (char*) frame;
+ char* current = &buffer[encoder.getPosition()];
+ uint32_t frameSize = current - start;
+ Encoder backfill(start, 4);
+ backfill.write(frameSize);
+ QPID_LOG(trace, "Completed encoding of frame of " << frameSize << " bytes");
+}
+
+
+std::size_t Sasl::read(const char* data, size_t available)
+{
+ size_t consumed = 0;
+ while (available - consumed > 4/*framesize*/) {
+ Decoder decoder(data+consumed, available-consumed);
+ //read frame-header
+ uint32_t frameSize = decoder.readUInt();
+ if (frameSize > decoder.getSize()) break;//don't have all the data for this frame yet
+
+ QPID_LOG(trace, "Reading SASL frame of size " << frameSize);
+ decoder.resetSize(frameSize);
+ uint8_t dataOffset = decoder.readUByte();
+ uint8_t frameType = decoder.readUByte();
+ if (frameType != 0x01) {
+ QPID_LOG(error, "Expected SASL frame; got type " << frameType);
+ }
+ uint16_t ignored = decoder.readUShort();
+ if (ignored) {
+ QPID_LOG(info, "Got non null bytes at end of SASL frame header");
+ }
+
+ //body is at offset 4*dataOffset from the start
+ size_t skip = dataOffset*4 - 8;
+ if (skip) {
+ QPID_LOG(info, "Offset for sasl frame was not as expected");
+ decoder.advance(skip);
+ }
+ decoder.read(*this);
+ consumed += decoder.getPosition();
+ }
+ return consumed;
+}
+
+std::size_t Sasl::write(char* data, size_t size)
+{
+ size_t available = encoder.getPosition();
+ if (available) {
+ size_t encoded = available > size ? size : available;
+ ::memcpy(data, &buffer[0], encoded);
+ size_t remainder = encoder.getPosition() - encoded;
+ if (remainder) {
+ //shuffle
+ ::memcpy(&buffer[0], &buffer[size], remainder);
+ }
+ encoder.resetPosition(remainder);
+ return encoded;
+ } else {
+ return 0;
+ }
+}
+
+std::size_t Sasl::readProtocolHeader(const char* buffer, std::size_t size)
+{
+ framing::ProtocolInitiation pi(qpid::framing::ProtocolVersion(1,0,qpid::framing::ProtocolVersion::SASL));
+ if (size >= pi.encodedSize()) {
+ qpid::framing::Buffer out(const_cast<char*>(buffer), size);
+ pi.decode(out);
+ QPID_LOG_CAT(debug, protocol, id << " read protocol header: " << pi);
+ return pi.encodedSize();
+ } else {
+ return 0;
+ }
+}
+std::size_t Sasl::writeProtocolHeader(char* buffer, std::size_t size)
+{
+ framing::ProtocolInitiation pi(qpid::framing::ProtocolVersion(1,0,qpid::framing::ProtocolVersion::SASL));
+ if (size >= pi.encodedSize()) {
+ QPID_LOG_CAT(debug, protocol, id << " writing protocol header: " << pi);
+ qpid::framing::Buffer out(buffer, size);
+ pi.encode(out);
+ return pi.encodedSize();
+ } else {
+ QPID_LOG_CAT(warning, protocol, id << " insufficient buffer for protocol header: " << size)
+ return 0;
+ }
+}
+
+}} // namespace qpid::amqp