Skip to content

Commit 5b3d0c0

Browse files
Fix Transcribe streaming "A complete signal was sent without the preceding empty frame"
1 parent f667b99 commit 5b3d0c0

File tree

7 files changed

+65
-36
lines changed

7 files changed

+65
-36
lines changed

generated/src/aws-cpp-sdk-transcribestreaming/include/aws/transcribestreaming/model/AudioStream.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@ namespace Model
3131
AudioStream& WriteAudioEvent(const AudioEvent& value)
3232
{
3333
Aws::Utils::Event::Message msg;
34-
msg.InsertEventHeader(":message-type", Aws::String("event"));
35-
msg.InsertEventHeader(":event-type", Aws::String("AudioEvent"));
36-
msg.InsertEventHeader(":content-type", Aws::String("application/octet-stream"));
37-
msg.WriteEventPayload(value.GetAudioChunk());
34+
if(!value.GetAudioChunk().empty())
35+
{
36+
msg.InsertEventHeader(":message-type", Aws::String("event"));
37+
msg.InsertEventHeader(":event-type", Aws::String("AudioEvent"));
38+
msg.InsertEventHeader(":content-type", Aws::String("application/octet-stream"));
39+
msg.WriteEventPayload(value.GetAudioChunk());
40+
}
3841
WriteEvent(msg);
3942
return *this;
4043
}

src/aws-cpp-sdk-core/include/aws/core/utils/event/EventStreamEncoder.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ namespace Aws
4949
bool InitEncodedStruct(const Aws::Utils::Event::Message& msg, aws_event_stream_message* encoded);
5050

5151
/**
52-
* Initialize signed C struct based on unsigned C struct.
52+
* Initialize signed C struct with a content of a payload message.
5353
* Returns true if successful.
54+
* signedmsg will contain an AWS Stream Event with a payload in a H2 frame payload section.
5455
* A successfully initialized struct must be cleaned up when you're done with it.
5556
*/
56-
bool InitSignedStruct(const aws_event_stream_message* msg, aws_event_stream_message* signedmsg);
57+
bool InitSignedStruct(const aws_event_stream_message* payload, aws_event_stream_message* signedmsg);
5758

5859
Aws::Client::AWSAuthSigner* m_signer;
5960
Aws::String m_signatureSeed;

src/aws-cpp-sdk-core/include/aws/core/utils/stream/ConcurrentStreamBuf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace Aws
3030
{
3131
public:
3232

33-
explicit ConcurrentStreamBuf(size_t bufferLength = 4 * 1024);
33+
explicit ConcurrentStreamBuf(size_t bufferLength = 8 * 1024);
3434

3535
void SetEof();
3636

src/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -188,31 +188,35 @@ bool AWSAuthEventStreamV4Signer::SignEventMessage(Event::Message& message, Aws::
188188
const auto nonSignatureHeadersHash = hashOutcome.GetResult();
189189
stringToSign << HashingUtils::HexEncode(nonSignatureHeadersHash) << Aws::Auth::AWSAuthHelper::NEWLINE;
190190

191-
if (message.GetEventPayload().empty())
192-
{
193-
AWS_LOGSTREAM_WARN(v4StreamingLogTag, "Attempting to sign an empty message (no payload and no headers). "
194-
"It is unlikely that this is the intended behavior.");
195-
}
196-
else
191+
if (!message.GetEventPayload().empty())
197192
{
198193
// use a preallocatedStreamBuf to avoid making a copy.
199194
// The Hashing API requires either Aws::String or IStream as input.
200195
// TODO: the hashing API should be accept 'unsigned char*' as input.
201196
Utils::Stream::PreallocatedStreamBuf streamBuf(message.GetEventPayload().data(), message.GetEventPayload().size());
202197
Aws::IOStream payload(&streamBuf);
203198
hashOutcome = m_hash.Calculate(payload);
199+
}
200+
else
201+
{
202+
// only a signature and a date will be in a frame
203+
AWS_LOGSTREAM_INFO(v4StreamingLogTag, "Signing an event with an empty payload");
204204

205-
if (!hashOutcome.IsSuccess())
206-
{
207-
AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers.");
208-
return false;
209-
}
210-
const auto payloadHash = hashOutcome.GetResult();
211-
stringToSign << HashingUtils::HexEncode(payloadHash);
212-
AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Payload hash - " << HashingUtils::HexEncode(payloadHash));
205+
hashOutcome = m_hash.Calculate(""); // SHA256 of an empty buffer
206+
}
207+
208+
if (!hashOutcome.IsSuccess())
209+
{
210+
AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers.");
211+
return false;
213212
}
213+
const auto payloadHash = hashOutcome.GetResult();
214+
stringToSign << HashingUtils::HexEncode(payloadHash);
215+
AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Payload hash - " << HashingUtils::HexEncode(payloadHash));
214216

215-
Aws::Utils::ByteBuffer finalSignatureDigest = GenerateSignature(m_credentialsProvider->GetAWSCredentials(), stringToSign.str(), simpleDate, m_region, m_serviceName);
217+
Aws::String canonicalRequestString = stringToSign.str();
218+
AWS_LOGSTREAM_TRACE(v4StreamingLogTag, "EventStream Event Canonical Request String: " << canonicalRequestString);
219+
Aws::Utils::ByteBuffer finalSignatureDigest = GenerateSignature(m_credentialsProvider->GetAWSCredentials(), canonicalRequestString, simpleDate, m_region, m_serviceName);
216220
const auto finalSignature = HashingUtils::HexEncode(finalSignatureDigest);
217221
AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Final computed signing hash: " << finalSignature);
218222
priorSignature = finalSignature;

src/aws-cpp-sdk-core/source/utils/event/EventStreamBuf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ namespace Aws
1111
{
1212
namespace Event
1313
{
14-
const size_t DEFAULT_BUF_SIZE = 1024;
14+
const size_t DEFAULT_BUF_SIZE = 8096;
1515

1616
EventStreamBuf::EventStreamBuf(EventStreamDecoder& decoder, size_t bufferLength) :
1717
m_byteBuffer(bufferLength),

src/aws-cpp-sdk-core/source/utils/event/EventStreamEncoder.cpp

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,18 @@ namespace Aws
8383
Aws::Vector<unsigned char> outputBits;
8484

8585
aws_event_stream_message encoded;
86-
if (InitEncodedStruct(msg, &encoded))
86+
aws_event_stream_message* encodedPayload = nullptr;
87+
bool msgEncodeSuccess = true; // empty message "successes" to encode
88+
if (!msg.GetEventHeaders().empty() || !msg.GetEventPayload().empty())
89+
{
90+
InitEncodedStruct(msg, &encoded);
91+
encodedPayload = &encoded;
92+
}
93+
94+
if (msgEncodeSuccess)
8795
{
8896
aws_event_stream_message signedMessage;
89-
if (InitSignedStruct(&encoded, &signedMessage))
97+
if (InitSignedStruct(encodedPayload, &signedMessage))
9098
{
9199
// success!
92100
const auto signedMessageBuffer = aws_event_stream_message_buffer(&signedMessage);
@@ -96,7 +104,10 @@ namespace Aws
96104

97105
aws_event_stream_message_clean_up(&signedMessage);
98106
}
99-
aws_event_stream_message_clean_up(&encoded);
107+
if (encodedPayload)
108+
{
109+
aws_event_stream_message_clean_up(encodedPayload);
110+
}
100111
}
101112

102113
return outputBits;
@@ -124,24 +135,27 @@ namespace Aws
124135
return success;
125136
}
126137

127-
bool EventStreamEncoder::InitSignedStruct(const aws_event_stream_message* msg, aws_event_stream_message* signedmsg)
138+
bool EventStreamEncoder::InitSignedStruct(const aws_event_stream_message* payload, aws_event_stream_message* signedmsg)
128139
{
129140
bool success = false;
130141

131-
const auto msgbuf = aws_event_stream_message_buffer(msg);
132-
const auto msglen = aws_event_stream_message_total_length(msg);
133142
Event::Message signedMessage;
134-
signedMessage.WriteEventPayload(msgbuf, msglen);
143+
if (payload)
144+
{
145+
const auto msgbuf = aws_event_stream_message_buffer(payload);
146+
const auto msglen = aws_event_stream_message_total_length(payload);
147+
signedMessage.WriteEventPayload(msgbuf, msglen);
148+
}
135149

136150
assert(m_signer);
137151
if (m_signer->SignEventMessage(signedMessage, m_signatureSeed))
138152
{
139153
aws_array_list headers;
140154
EncodeHeaders(signedMessage, &headers);
141155

142-
aws_byte_buf payload = aws_byte_buf_from_array(signedMessage.GetEventPayload().data(), signedMessage.GetEventPayload().size());
156+
aws_byte_buf signedPayload = aws_byte_buf_from_array(signedMessage.GetEventPayload().data(), signedMessage.GetEventPayload().size());
143157

144-
if(aws_event_stream_message_init(signedmsg, get_aws_allocator(), &headers, &payload) == AWS_OP_SUCCESS)
158+
if(aws_event_stream_message_init(signedmsg, get_aws_allocator(), &headers, &signedPayload) == AWS_OP_SUCCESS)
145159
{
146160
success = true;
147161
}

tools/code-generation/generator/src/main/resources/com/amazonaws/util/awsclientgenerator/velocity/cpp/json/EventStreamHeader.vm

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,24 @@ namespace Model
4848
${typeInfo.className}& Write${entry.value.shape.name}(const ${entry.value.shape.name}& value)
4949
{
5050
Aws::Utils::Event::Message msg;
51+
#if(!$entry.value.shape.eventPayloadType.equals("blob"))
5152
msg.InsertEventHeader(":message-type", Aws::String("event"));
5253
msg.InsertEventHeader(":event-type", Aws::String("${entry.value.shape.name}"));
53-
#if($entry.value.shape.eventPayloadType.equals("blob"))
54-
msg.InsertEventHeader(":content-type", Aws::String("application/octet-stream"));
55-
msg.WriteEventPayload(value.Get$CppViewHelper.capitalizeFirstChar(${entry.value.shape.eventPayloadMemberName})());
56-
#elseif($entry.value.shape.eventPayloadType.equals("string"))
54+
#if($entry.value.shape.eventPayloadType.equals("string"))
5755
msg.InsertEventHeader(":content-type", Aws::String("text/plain"));
5856
msg.WriteEventPayload(value.Get$CppViewHelper.capitalizeFirstChar(${entry.value.shape.eventPayloadMemberName})()));
5957
#elseif($entry.value.shape.eventPayloadType.equals("structure") || $entry.value.shape.eventPayloadType.equals("list"))
6058
msg.InsertEventHeader(":content-type", Aws::String("application/json"));
6159
msg.WriteEventPayload(value.Jsonize().View().WriteCompact());
60+
#end
61+
#else##if($entry.value.shape.eventPayloadType.equals("blob"))
62+
if(!value.Get$CppViewHelper.capitalizeFirstChar(${entry.value.shape.eventPayloadMemberName})().empty())
63+
{
64+
msg.InsertEventHeader(":message-type", Aws::String("event"));
65+
msg.InsertEventHeader(":event-type", Aws::String("${entry.value.shape.name}"));
66+
msg.InsertEventHeader(":content-type", Aws::String("application/octet-stream"));
67+
msg.WriteEventPayload(value.Get$CppViewHelper.capitalizeFirstChar(${entry.value.shape.eventPayloadMemberName})());
68+
}
6269
#end
6370
WriteEvent(msg);
6471
return *this;

0 commit comments

Comments
 (0)