Skip to content

Commit 836f4de

Browse files
committed
bulk push_back to Deque, fix typo
fix Potential overflow in SSRC generation fix Loop/erase skipping a participant
1 parent 8a738b8 commit 836f4de

3 files changed

Lines changed: 79 additions & 20 deletions

File tree

src/AppleMIDI.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class AppleMIDISession
5252
this->port = port;
5353
#ifdef KEEP_SESSION_NAME
5454
strncpy(this->localName, sessionName, Settings::MaxSessionNameLen);
55+
this->localName[Settings::MaxSessionNameLen] = '\0';
5556
#endif
5657

5758
#ifdef ONE_PARTICIPANT
@@ -117,6 +118,7 @@ class AppleMIDISession
117118
AppleMIDISession &setName(const char *sessionName)
118119
{
119120
strncpy(this->localName, sessionName, Settings::MaxSessionNameLen);
121+
this->localName[Settings::MaxSessionNameLen] = '\0';
120122
return *this;
121123
};
122124
#else
@@ -170,7 +172,7 @@ class AppleMIDISession
170172
// this is our SSRC
171173
//
172174
// NOTE: Arduino random only goes to INT32_MAX (not UINT32_MAX)
173-
this->ssrc = random(1, INT32_MAX) * 2;
175+
this->ssrc = random(1, INT32_MAX / 2) * 2;
174176

175177
controlPort.begin(port);
176178
dataPort.begin(port + 1);

src/AppleMIDI.hpp

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22

33
#include "AppleMIDI_Namespace.h"
4+
#include <string.h>
45

56
BEGIN_APPLEMIDI_NAMESPACE
67

@@ -17,8 +18,7 @@ size_t AppleMIDISession<UdpClass, Settings, Platform>::readControlPackets()
1718
auto bytesRead = controlPort.read(packetBuffer, bytesToRead);
1819
packetSize -= bytesRead;
1920

20-
for (auto i = 0; i < bytesRead; i++)
21-
controlBuffer.push_back(packetBuffer[i]);
21+
controlBuffer.push_back(packetBuffer, bytesRead);
2222
}
2323

2424
return controlBuffer.size();
@@ -65,8 +65,7 @@ size_t AppleMIDISession<UdpClass, Settings, Platform>::readDataPackets()
6565
auto bytesRead = dataPort.read(packetBuffer, bytesToRead);
6666
packetSize -= bytesRead;
6767

68-
for (auto i = 0; i < bytesRead; i++)
69-
dataBuffer.push_back(packetBuffer[i]);
68+
dataBuffer.push_back(packetBuffer, bytesRead);
7069
}
7170

7271
return dataBuffer.size();
@@ -149,6 +148,7 @@ void AppleMIDISession<UdpClass, Settings, Platform>::ReceivedControlInvitation(A
149148
participant.lastSyncExchangeTime = now;
150149
#ifdef KEEP_SESSION_NAME
151150
strncpy(participant.sessionName, invitation.sessionName, Settings::MaxSessionNameLen);
151+
participant.sessionName[Settings::MaxSessionNameLen] = '\0';
152152
#endif
153153

154154
#ifdef KEEP_SESSION_NAME
@@ -690,10 +690,12 @@ void AppleMIDISession<UdpClass, Settings, Platform>::writeRtpMidiBuffer(Particip
690690
return;
691691
}
692692

693-
// write rtp header
694-
dataPort.write((uint8_t *)&rtp, sizeof(rtp));
693+
// Write RTP + rtpMIDI in a single packet to reduce overhead.
694+
uint8_t packet[sizeof(Rtp) + 2 + Settings::MaxBufferSize];
695+
size_t offset = 0;
696+
memcpy(packet + offset, &rtp, sizeof(rtp));
697+
offset += sizeof(rtp);
695698

696-
// Write rtpMIDI section
697699
RtpMIDI_t rtpMidi;
698700

699701
// 0 1 2 3
@@ -711,21 +713,22 @@ void AppleMIDISession<UdpClass, Settings, Platform>::writeRtpMidiBuffer(Particip
711713
{ // Short header
712714
rtpMidi.flags |= (uint8_t)bufferLen;
713715
rtpMidi.flags &= ~RTP_MIDI_CS_FLAG_B; // short header, clear B-FLAG
714-
dataPort.write(rtpMidi.flags);
716+
packet[offset++] = rtpMidi.flags;
715717
}
716718
else
717719
{ // Long header
718720
rtpMidi.flags |= (uint8_t)(bufferLen >> 8);
719721
rtpMidi.flags |= RTP_MIDI_CS_FLAG_B; // set B-FLAG for long header
720-
dataPort.write(rtpMidi.flags);
721-
dataPort.write((uint8_t)(bufferLen));
722+
packet[offset++] = rtpMidi.flags;
723+
packet[offset++] = (uint8_t)(bufferLen);
722724
}
723725

724726
// write out the MIDI Section
725727
for (size_t i = 0; i < bufferLen; i++)
726-
dataPort.write(outMidiBuffer[i]);
728+
packet[offset++] = outMidiBuffer[i];
727729

728730
// *No* journal section (Not supported)
731+
dataPort.write(packet, offset);
729732

730733
dataPort.endPacket();
731734
dataPort.flush();
@@ -743,19 +746,28 @@ template <class UdpClass, class Settings, class Platform>
743746
void AppleMIDISession<UdpClass, Settings, Platform>::manageSynchronization()
744747
{
745748
#ifndef ONE_PARTICIPANT
746-
for (size_t i = 0; i < participants.size(); i++)
749+
for (size_t i = 0; i < participants.size();)
747750
#endif
748751
{
749752
#ifndef ONE_PARTICIPANT
750753
auto pParticipant = &participants[i];
751-
if (pParticipant->ssrc == 0) continue;
754+
if (pParticipant->ssrc == 0)
755+
{
756+
i++;
757+
continue;
758+
}
752759
#else
753760
auto pParticipant = &participant;
754761
if (pParticipant->ssrc == 0) return;
755762
#endif
756763
#ifdef APPLEMIDI_INITIATOR
757764
if (pParticipant->invitationStatus != Connected)
765+
{
766+
#ifndef ONE_PARTICIPANT
767+
i++;
768+
#endif
758769
continue;
770+
}
759771

760772
// Only for Initiators that are Connected
761773
if (pParticipant->kind == Listener)
@@ -772,6 +784,7 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSynchronization()
772784
sendEndSession(pParticipant);
773785
#ifndef ONE_PARTICIPANT
774786
participants.erase(i);
787+
continue;
775788
#else
776789
participant.ssrc = 0;
777790
#endif
@@ -783,6 +796,9 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSynchronization()
783796
(pParticipant->synchronizing) ? manageSynchronizationInitiatorInvites(i)
784797
: manageSynchronizationInitiatorHeartBeat(pParticipant);
785798
}
799+
#endif
800+
#ifndef ONE_PARTICIPANT
801+
i++;
786802
#endif
787803
}
788804
}
@@ -882,7 +898,7 @@ template <class UdpClass, class Settings, class Platform>
882898
void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
883899
{
884900
#ifndef ONE_PARTICIPANT
885-
for (auto i = 0; i < participants.size(); i++)
901+
for (auto i = 0; i < participants.size();)
886902
#endif
887903
{
888904
#ifndef ONE_PARTICIPANT
@@ -893,7 +909,10 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
893909

894910
if (pParticipant->kind == Listener)
895911
#ifndef ONE_PARTICIPANT
912+
{
913+
i++;
896914
continue;
915+
}
897916
#else
898917
return;
899918
#endif
@@ -911,7 +930,10 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
911930

912931
if (pParticipant->invitationStatus == Connected)
913932
#ifndef ONE_PARTICIPANT
933+
{
934+
i++;
914935
continue;
936+
}
915937
#else
916938
return;
917939
#endif
@@ -930,12 +952,9 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
930952

931953
#ifndef ONE_PARTICIPANT
932954
participants.erase(i);
933-
#else
934-
participant.ssrc = 0;
935-
#endif
936-
#ifndef ONE_PARTICIPANT
937955
continue;
938956
#else
957+
participant.ssrc = 0;
939958
return;
940959
#endif
941960
}
@@ -964,6 +983,9 @@ void AppleMIDISession<UdpClass, Settings, Platform>::manageSessionInvites()
964983
pParticipant->invitationStatus = AwaitingDataInvitationAccepted;
965984
}
966985
}
986+
#ifndef ONE_PARTICIPANT
987+
i++;
988+
#endif
967989
}
968990
}
969991

@@ -1054,7 +1076,7 @@ void AppleMIDISession<UdpClass, Settings, Platform>::sendEndSession()
10541076
participants.pop_front();
10551077
}
10561078
#else
1057-
if (participant.src != 0)
1079+
if (participant.ssrc != 0)
10581080
{
10591081
sendEndSession(&participant);
10601082
participant.ssrc = 0;

src/utility/Deque.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#pragma once
22

3+
#include <string.h>
4+
35
BEGIN_APPLEMIDI_NAMESPACE
46

57
template<typename T, size_t Size>
@@ -25,6 +27,7 @@ class Deque {
2527
const T & back() const;
2628
void push_front(const T &);
2729
void push_back(const T &);
30+
size_t push_back(const T *, size_t);
2831
void pop_front();
2932
void pop_back();
3033

@@ -124,6 +127,38 @@ void Deque<T, Size>::push_back(const T &value)
124127
}
125128
}
126129

130+
template<typename T, size_t Size>
131+
size_t Deque<T, Size>::push_back(const T *values, size_t count)
132+
{
133+
if (values == nullptr || count == 0)
134+
return 0;
135+
136+
const size_t available = free();
137+
if (available == 0)
138+
return 0;
139+
140+
const size_t toWrite = (count < available) ? count : available;
141+
142+
if (empty())
143+
_tail = _head;
144+
145+
size_t first = toWrite;
146+
if (_head + first > Size)
147+
first = Size - _head;
148+
149+
memcpy(&_data[_head], values, first * sizeof(T));
150+
_head = (_head + first) % Size;
151+
152+
const size_t remaining = toWrite - first;
153+
if (remaining > 0)
154+
{
155+
memcpy(&_data[_head], values + first, remaining * sizeof(T));
156+
_head = (_head + remaining) % Size;
157+
}
158+
159+
return toWrite;
160+
}
161+
127162
template<typename T, size_t Size>
128163
void Deque<T, Size>::pop_front() {
129164
if (empty()) // if empty, do nothing.

0 commit comments

Comments
 (0)