Transceiver52M: Reduce and place bounds checking on I/O buffers

Previous send and receive buffers at the radio interface were
arbitrarily set to a sufficient size. For normal (non-resampling)
devices, use a block (chunk) size of 625 samples. For 64 or 100
MHz resampling devices, use 4 times the reduced resampling
numerator or denominator and provide bounds checking where
appropriate.

Signed-off-by: Thomas Tsou <tom@tsou.cc>
diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp
index a633738..a8a54a5 100644
--- a/Transceiver52M/radioInterface.cpp
+++ b/Transceiver52M/radioInterface.cpp
@@ -30,8 +30,8 @@
 #include "convert.h"
 }
 
-#define INCHUNK		(625 * SAMPSPERSYM)
-#define OUTCHUNK	(625 * SAMPSPERSYM)
+#define CHUNK		625
+#define NUMCHUNKS	4
 
 RadioInterface::RadioInterface(RadioDevice *wRadio,
 			       int wReceiveOffset,
@@ -58,11 +58,11 @@
 
   close();
 
-  sendBuffer = new signalVector(OUTCHUNK * 20);
-  recvBuffer = new signalVector(INCHUNK * 20);
+  sendBuffer = new signalVector(CHUNK * mSPSTx);
+  recvBuffer = new signalVector(NUMCHUNKS * CHUNK * mSPSRx);
 
-  convertSendBuffer = new short[OUTCHUNK * 2 * 20];
-  convertRecvBuffer = new short[OUTCHUNK * 2 * 2];
+  convertSendBuffer = new short[sendBuffer->size() * 2];
+  convertRecvBuffer = new short[recvBuffer->size() * 2];
 
   sendCursor = 0;
   recvCursor = 0;
@@ -276,23 +276,26 @@
 void RadioInterface::pullBuffer()
 {
   bool local_underrun;
-  int num_recv, len = OUTCHUNK / mSPSTx;
+  int num_recv;
   float *output;
 
+  if (recvCursor > recvBuffer->size() - CHUNK)
+    return;
+
   /* Outer buffer access size is fixed */
   num_recv = mRadio->readSamples(convertRecvBuffer,
-                                 len,
+                                 CHUNK,
                                  &overrun,
                                  readTimestamp,
                                  &local_underrun);
-  if (num_recv != len) {
+  if (num_recv != CHUNK) {
           LOG(ALERT) << "Receive error " << num_recv;
           return;
   }
 
   output = (float *) (recvBuffer->begin() + recvCursor);
 
-  convert_short_float(output, convertRecvBuffer, 2 * len);
+  convert_short_float(output, convertRecvBuffer, 2 * num_recv);
 
   underrun |= local_underrun;
 
@@ -305,9 +308,12 @@
 {
   int num_sent;
 
-  if (sendCursor < INCHUNK)
+  if (sendCursor < CHUNK)
     return;
 
+  if (sendCursor > sendBuffer->size())
+    LOG(ALERT) << "Send buffer overflow";
+
   convert_float_short(convertSendBuffer,
                       (float *) sendBuffer->begin(),
                       powerScaling, 2 * sendCursor);
diff --git a/Transceiver52M/radioInterfaceResamp.cpp b/Transceiver52M/radioInterfaceResamp.cpp
index f857df9..c3b4396 100644
--- a/Transceiver52M/radioInterfaceResamp.cpp
+++ b/Transceiver52M/radioInterfaceResamp.cpp
@@ -36,6 +36,9 @@
 #define RESAMP_100M_INRATE			52
 #define RESAMP_100M_OUTRATE			75
 
+/* Universal resampling parameters */
+#define NUMCHUNKS				24
+
 /*
  * Resampling filter bandwidth scaling factor
  *   This narrows the filter cutoff relative to the output bandwidth
@@ -116,6 +119,11 @@
 	resamp_inchunk = resamp_inrate * 4;
 	resamp_outchunk = resamp_outrate * 4;
 
+	if (resamp_inchunk  * NUMCHUNKS < 157 * mSPSTx * 2) {
+		LOG(ALERT) << "Invalid inner chunk size " << resamp_inchunk;
+		return false;
+	}
+
 	if (mSPSTx == 4)
 		cutoff = RESAMP_TX4_FILTER;
 
@@ -137,16 +145,17 @@
 	 * and requires headroom equivalent to the filter length. Low
 	 * rate buffers are allocated in the main radio interface code.
 	 */
-	innerSendBuffer = new signalVector(resamp_inchunk * 20,
-					   upsampler->len());
-	outerSendBuffer = new signalVector(resamp_outchunk * 20);
+	innerSendBuffer =
+		new signalVector(NUMCHUNKS * resamp_inchunk, upsampler->len());
+	outerSendBuffer =
+		new signalVector(NUMCHUNKS * resamp_outchunk);
+	outerRecvBuffer =
+		new signalVector(resamp_outchunk, dnsampler->len());
+	innerRecvBuffer =
+		new signalVector(NUMCHUNKS * resamp_inchunk / mSPSTx);
 
-	outerRecvBuffer = new signalVector(resamp_outchunk * 2,
-					   dnsampler->len());
-	innerRecvBuffer = new signalVector(resamp_inchunk * 20);
-
-	convertSendBuffer = new short[resamp_outchunk * 2 * 20];
-	convertRecvBuffer = new short[resamp_outchunk * 2 * 2];
+	convertSendBuffer = new short[outerSendBuffer->size() * 2];
+	convertRecvBuffer = new short[outerRecvBuffer->size() * 2];
 
 	sendBuffer = innerSendBuffer;
 	recvBuffer = innerRecvBuffer;
@@ -159,35 +168,37 @@
 {
 	bool local_underrun;
 	int rc, num_recv;
-	int inner_len = resamp_inchunk;
-	int outer_len = resamp_outchunk;
+
+	if (recvCursor > innerRecvBuffer->size() - resamp_inchunk)
+		return;
 
 	/* Outer buffer access size is fixed */
 	num_recv = mRadio->readSamples(convertRecvBuffer,
-				       outer_len,
+				       resamp_outchunk,
 				       &overrun,
 				       readTimestamp,
 				       &local_underrun);
-	if (num_recv != outer_len) {
+	if (num_recv != resamp_outchunk) {
 		LOG(ALERT) << "Receive error " << num_recv;
 		return;
 	}
 
 	convert_short_float((float *) outerRecvBuffer->begin(),
-			    convertRecvBuffer, 2 * outer_len);
+			    convertRecvBuffer, 2 * resamp_outchunk);
 
 	underrun |= local_underrun;
-	readTimestamp += (TIMESTAMP) num_recv;
+	readTimestamp += (TIMESTAMP) resamp_outchunk;
 
 	/* Write to the end of the inner receive buffer */
-	rc = dnsampler->rotate((float *) outerRecvBuffer->begin(), outer_len,
+	rc = dnsampler->rotate((float *) outerRecvBuffer->begin(),
+			       resamp_outchunk,
 			       (float *) (innerRecvBuffer->begin() + recvCursor),
-			       inner_len);
+			       resamp_inchunk);
 	if (rc < 0) {
 		LOG(ALERT) << "Sample rate upsampling error";
 	}
 
-	recvCursor += inner_len;
+	recvCursor += resamp_inchunk;
 }
 
 /* Send a timestamped chunk to the device */
@@ -199,9 +210,10 @@
 	if (sendCursor < resamp_inchunk)
 		return;
 
+	if (sendCursor > innerSendBuffer->size())
+		LOG(ALERT) << "Send buffer overflow";
+
 	chunks = sendCursor / resamp_inchunk;
-	if (chunks > 8)
-		chunks = 8;
 
 	inner_len = chunks * resamp_inchunk;
 	outer_len = chunks * resamp_outchunk;