Why this base64 function stop working when increasing max length? - c++

I am using this class to encode/decode text to base64.
It works fine with MAX_LEN up to 512 but if I increase it to 1024 the decode function returns and empty var.
This is the function:
char* Base64::decode(char *src)
{
unsigned six, dix;
unsigned int d_len = MAX_LEN;
memset(dst,'\0', MAX_LEN);
unsigned s_len = strlen(src);
dix = 0;
for (six = 0; six < s_len; six += 4)
{
unsigned long sr;
unsigned ix;
sr = 0;
for (ix = 0; ix < 4; ++ix)
{
int sextet;
if (six+ix >= s_len)
return NULL;
if ((sextet = tlu(*(src+six+ix))) < 0)
break;
sr <<= 6;
sr |= (sextet & 0x3f);
}
switch (ix)
{
case 0: // end of data, no padding
return 0;
case 1: // can't happen
return NULL;
case 2: // 1 result byte
sr >>= 4;
if (dix > d_len) return NULL;
*(dst+dix) = (sr & 0xff);
++dix;
break;
case 3: // 2 result bytes
sr >>= 2;
if (dix+1 > d_len) return NULL;
*(dst+dix+1) = (sr & 0xff);
sr >>= 8;
*(dst+dix) = (sr & 0xff);
dix += 2;
break;
case 4: // 3 result bytes
if (dix+2 > d_len) return NULL;
*(dst+dix+2) = (sr & 0xff);
sr >>= 8;
*(dst+dix+1) = (sr & 0xff);
sr >>= 8;
*(dst+dix) = (sr & 0xff);
dix += 3;
break;
}
}
return dst;
}
Why could be causing this?

Odds are dst is not sized correctly to hold all 1024 bytes. Without seeing dst's declaration there is no way to be sure.

Related

if statement doesn't work on Nucleo64 but it does on Maple mini

I have a code that works on Maple Mini but I have to change hardware to Nucleo F030r8 because it has more ADC's and it totally sucks.
In the modbus_update() function there is a check of the size of inputBuffer and the following code should run only if the value of this variable is bigger than 0.
if (inputBuffer > 0 && micros() - microsFlag >= T3_5) {
...
}
But it runs even if value of inputBuffer is exactly 0. The strange thing is that this code (with different serial ports opening method) runs perfectly on Maple Mini. Does anyone have any idea what can be be the problem?
Here is the whole code:
#define BAUDRATE 19200
#define RE_PIN PC12
#define TE_PIN PF4
#define LED_PIN LED_BUILTIN
#define SLAVE_ID 1
#define BUFFER_SIZE 256 // max frame size
#define READ_INTERNAL_REGISTERS 4 // function code
#define MIN_REGISTER_ADDRESS 30001
#define MAX_REGISTER_ADDRESS 30020
#define MAX_SENSORS_PER_ROW 10
#define SENSORS_PER_ROW 7
#define MAX_ROWS 2
#define ROWS 1
#define DEBUG true
#define INVALID_VALUE 0x7FFF
const byte INPUTS[] = {PA0, PA1, PA4, PB0, PC1, PC0};
unsigned char frame[BUFFER_SIZE];
unsigned char functionCode;
unsigned int T1;
unsigned int T1_5; // inter character time out
unsigned int T3_5; // frame delay
unsigned long millisFlag = 0;
unsigned long microsFlag = 0;
unsigned char inputBuffer = 0;
int dlyCounter = 0;
int16_t sensorVals[MAX_SENSORS_PER_ROW * MAX_ROWS];
/*
HardwareSerial *modbus = &Serial;
HardwareSerial Serial1(PA10, PA9);
HardwareSerial *debug = &Serial1;
*/
HardwareSerial debug(PA10, PA9);
void setup() {
pinMode(LED_PIN, OUTPUT);
for (int i = 0; i < SENSORS_PER_ROW; i++) {
pinMode(INPUTS[i], INPUT_PULLUP);
}
debug.begin(BAUDRATE, SERIAL_8E1);
modbus_configure(BAUDRATE, 0); // baud rate, low latency
microsFlag = micros();
}
void loop() {
readSensorVals(100);
modbus_update();
}
unsigned int modbus_update() {
unsigned char overflow = 0;
while (Serial.available()) {
if (overflow) {
Serial.read(); // empty the input buffer
} else {
if (inputBuffer == BUFFER_SIZE) {
overflow = 1;
} else {
frame[inputBuffer] = Serial.read();
inputBuffer++;
}
}
microsFlag = micros();
}
// If an overflow occurred return to the main sketch
// without responding to the request i.e. force a timeout
if (overflow) {
debug.println("Error: input buffer overflow");
return 0;
}
// if inter frame delay occurred, check the incoming package
if (inputBuffer > 0 && micros() - microsFlag >= T3_5) {
debug.println("\nIncoming frame:");
for (int i = 0; i < inputBuffer; i++) {
debug.print(frame[i], HEX);
debug.print(" ");
}
debug.println();
// check CRC
unsigned int crc = ((frame[inputBuffer - 2] << 8) | frame[inputBuffer - 1]); // combine the crc Low & High bytes
if (calculateCRC(frame, inputBuffer - 2) != crc) {
debug.println("Error: checksum failed");
inputBuffer = 0;
return 0;
}
debug.println("CRC OK");
// check ID
unsigned char id = frame[0];
if (id > 242) {
debug.println("Error: Invalid ID");
inputBuffer = 0;
return 0;
}
// check if it's a broadcast message
if (id == 0) {
debug.println("Broadcast message");
inputBuffer = 0;
return 0;
}
if (id != SLAVE_ID) {
debug.println("Not my ID");
inputBuffer = 0;
return 0;
}
debug.println("ID OK");
// check function code
functionCode = frame[1];
if (functionCode != READ_INTERNAL_REGISTERS) {
debug.println("Exception: illegal function");
exceptionResponse(1);
inputBuffer = 0;
return 0;
}
debug.println("Function code OK");
// check frame size (function 4 frame MUST be 8 bytes long)
if (inputBuffer != 8) {
// some workaround here:
//if (inputBuffer != 8 || !(inputBuffer == 9 && frame[inputBuffer] == 0)) {
debug.println("Error: inaccurate frame length");
inputBuffer = 0;
return 0;
}
debug.println("Frame size OK");
// check data address range
unsigned int noOfRegisters = ((frame[4] << 8) | frame[5]); // combine the number of register bytes
if (noOfRegisters > 125) {
debug.println("Exception: illegal data address");
exceptionResponse(2);
inputBuffer = 0;
return 0;
}
unsigned int firstRegAddress = ((frame[2] << 8) | frame[3]); // combine the starting address bytes
debug.print("First address: ");
debug.println(firstRegAddress);
unsigned int lastRegAddress = firstRegAddress + noOfRegisters - 1;
debug.print("Last address: ");
debug.println(lastRegAddress);
unsigned char noOfBytes = noOfRegisters * 2;
unsigned char responseFrameSize = 5 + noOfBytes; // ID, functionCode, noOfBytes, (dataLo + dataHi) * number of registers, crcLo, crcHi
unsigned char responseFrame[responseFrameSize];
responseFrame[0] = SLAVE_ID;
responseFrame[1] = 0x04;
responseFrame[2] = noOfBytes;
unsigned char address = 3; // PDU starts at the 4th byte
for (int index = (int)(firstRegAddress - MIN_REGISTER_ADDRESS); index <= (int)(lastRegAddress - MIN_REGISTER_ADDRESS); index++) {
int16_t temp = (index >= 0 && index < MAX_ROWS * MAX_SENSORS_PER_ROW) ? sensorVals[index] : INVALID_VALUE;
responseFrame[address] = temp >> 8; // split the register into 2 bytes
address++;
responseFrame[address] = temp & 0xFF;
address++;
}
unsigned int crc16 = calculateCRC(responseFrame, responseFrameSize - 2);
responseFrame[responseFrameSize - 2] = crc16 >> 8; // split crc into 2 bytes
responseFrame[responseFrameSize - 1] = crc16 & 0xFF;
debug.println("Frame to send:");
for (int i = 0; i < responseFrameSize; i++) {
debug.print(responseFrame[i], HEX);
debug.print(" ");
}
debug.println();
sendPacket(responseFrame, responseFrameSize);
inputBuffer = 0;
while (Serial.available()) { // empty input buffer
Serial.read();
}
}
}
void modbus_configure(long baud, unsigned char _lowLatency) {
Serial.begin(baud, SERIAL_8E1);
pinMode(TE_PIN, OUTPUT);
pinMode(RE_PIN, OUTPUT);
rxEnable(); // pin 0 & pin 1 are reserved for RX/TX. To disable set TE and RE pin < 2
if (baud == 1000000 && _lowLatency) {
T1 = 1;
T1_5 = 1;
T3_5 = 10;
} else if (baud >= 115200 && _lowLatency) {
T1 = 50;
T1_5 = 75;
T3_5 = 175;
} else if (baud > 19200) {
T1 = 500;
T1_5 = 750;
T3_5 = 1750;
} else {
T1 = 10000000 / baud;
T1_5 = 15000000 / baud; // 1T * 1.5 = T1.5
T3_5 = 35000000 / baud; // 1T * 3.5 = T3.5
}
}
void exceptionResponse(unsigned char exception) {
unsigned char responseFrameSize = 5;
unsigned char responseFrame[responseFrameSize];
responseFrame[0] = SLAVE_ID;
responseFrame[1] = (functionCode | 0x80); // set the MSB bit high, informs the master of an exception
responseFrame[2] = exception;
unsigned int crc16 = calculateCRC(responseFrame, 3); // ID, functionCode + 0x80, exception code == 3 bytes
responseFrame[3] = crc16 >> 8;
responseFrame[4] = crc16 & 0xFF;
sendPacket(responseFrame, responseFrameSize); // exception response is always 5 bytes (ID, functionCode + 0x80, exception code, 2 bytes crc)
}
unsigned int calculateCRC(unsigned char f[], byte bufferSize) {
unsigned int temp, temp2, flag;
temp = 0xFFFF;
for (unsigned char i = 0; i < bufferSize; i++) {
temp = temp ^ f[i];
for (unsigned char j = 1; j <= 8; j++) {
flag = temp & 0x0001;
temp >>= 1;
if (flag)
temp ^= 0xA001;
}
}
// Reverse byte order.
temp2 = temp >> 8;
temp = (temp << 8) | temp2;
temp &= 0xFFFF;
return temp; // the returned value is already swapped - crcLo byte is first & crcHi byte is last
}
void rxEnable() {
if (TE_PIN > 1 && RE_PIN > 1) {
digitalWrite(TE_PIN, LOW);
digitalWrite(RE_PIN, LOW);
digitalWrite(LED_PIN, LOW);
}
}
void txEnable() {
if (TE_PIN > 1 && RE_PIN > 1) {
digitalWrite(TE_PIN, HIGH);
digitalWrite(RE_PIN, HIGH);
digitalWrite(LED_PIN, HIGH);
}
}
void sendPacket(unsigned char f[], unsigned char bufferSize) {
txEnable();
delayMicroseconds(T3_5);
for (unsigned char i = 0; i < bufferSize; i++) {
Serial.write(f[i]);
}
Serial.flush();
delayMicroseconds(T3_5); // allow frame delay to indicate end of transmission
rxEnable();
}
// #param dly delay between sensor readings in milliseconds
void readSensorVals(int dly) {
if (millis() != millisFlag) {
dlyCounter++;
millisFlag = millis();
}
if (dlyCounter >= dly) { // read sensor values
for (int i = 0; i < MAX_ROWS; i++) {
for (int j = 0; j < MAX_SENSORS_PER_ROW; j++) {
int actualIndex = i * MAX_SENSORS_PER_ROW + j;
if (i < ROWS && j < SENSORS_PER_ROW) {
sensorVals[actualIndex] = random(20, 30);
//sensorVals[actualIndex] = (4096 - analogRead(INPUTS[j])) / 20 - 133;
} else {
sensorVals[actualIndex] = INVALID_VALUE;
}
}
}
dlyCounter = 0;
}
}

How to compute variable byte encoding of a postings list?

Lets say I have a postings list of 6 numbers 21992 23523 27822 28002 31010 33122. What would be the process to converting them to variable byte encoding?
void encode(int value, char* code_list, int& len) {
int bit_value = 0;
int bit_num = 0;
if (value < 128) {
bit_num = 1;
} else if (value < 16384) {
bit_num = 2;
bit_value = 1;
} else if (value < 2097152) {
bit_num = 3;
bit_value = 3;
} else {
bit_num = 4;
bit_value = 7;
}
value <<= bit_num;
value += bit_value;
memcpy(code_list + len, (char*) &value, bit_num);
len += bit_num;
}

Websocket Poco can't receive big data

I downloaded and built Poco project from Poco and run WebsocketServer project in poco-1.7.6\Net\samples\WebSocketServer.
When I worked with small data that is smaller 128 KB (131072 bytes), it work perfectly. But if I work with bigger data (I need to send 20 MB), my data will be cut so server don't receive data enough.
Here is code that I copy in project:
WebSocket ws(request, response);
char *buffer = new char[1000000]; // It just receive 131072 bytes
int flags;
int n;
do
{
n = ws.receiveFrame(buffer, sizeof(buffer), flags);
ws.sendFrame(buffer, tmp.length(), flags);
} while (n > 0 || (flags & WebSocket::FRAME_OP_BITMASK) != WebSocket::FRAME_OP_CLOSE);
delete[] buffer;
Deframe code:
int WebSocketImpl::receiveBytes(void* buffer, int length, int)
{
char header[MAX_HEADER_LENGTH];
int n = receiveNBytes(header, 2);
if (n <= 0)
{
_frameFlags = 0;
return n;
}
poco_assert (n == 2);
Poco::UInt8 lengthByte = static_cast<Poco::UInt8>(header[1]);
int maskOffset = 0;
if (lengthByte & FRAME_FLAG_MASK) maskOffset += 4;
lengthByte &= 0x7f;
if (lengthByte > 0 || maskOffset > 0)
{
if (lengthByte + 2 + maskOffset < MAX_HEADER_LENGTH)
{
n = receiveNBytes(header + 2, lengthByte + maskOffset);
}
else
{
n = receiveNBytes(header + 2, MAX_HEADER_LENGTH - 2);
}
if (n <= 0) throw WebSocketException("Incomplete header received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
n += 2;
}
Poco::MemoryInputStream istr(header, n);
Poco::BinaryReader reader(istr, Poco::BinaryReader::NETWORK_BYTE_ORDER);
Poco::UInt8 flags;
char mask[4];
reader >> flags >> lengthByte;
_frameFlags = flags;
int payloadLength = 0;
int payloadOffset = 2;
if ((lengthByte & 0x7f) == 127)
{
Poco::UInt64 l;
reader >> l;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %Lu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadOffset += 8;
}
else if ((lengthByte & 0x7f) == 126)
{
Poco::UInt16 l;
//lenBuffer = l;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %hu", l), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
payloadOffset += 2;
}
else
{
Poco::UInt8 l = lengthByte & 0x7f;
if (l > length) throw WebSocketException(Poco::format("Insufficient buffer for payload size %u", unsigned(l)), WebSocket::WS_ERR_PAYLOAD_TOO_BIG);
payloadLength = static_cast<int>(l);
}
if (lengthByte & FRAME_FLAG_MASK)
{
reader.readRaw(mask, 4);
payloadOffset += 4;
}
int received = 0;
if (payloadOffset < n)
{
std::memcpy(buffer, header + payloadOffset, n - payloadOffset);
received = n - payloadOffset;
}
if (received < payloadLength)
{
n = receiveNBytes(reinterpret_cast<char*>(buffer) + received, payloadLength - received);
if (n <= 0) throw WebSocketException("Incomplete frame received", WebSocket::WS_ERR_INCOMPLETE_FRAME);
received += n;
}
if (lengthByte & FRAME_FLAG_MASK)
{
char* p = reinterpret_cast<char*>(buffer);
for (int i = 0; i < received; i++)
{
p[i] ^= mask[i % 4];
}
}
return received;
}
Can anyone help me, please!
P/s: Sorry about my English
UPDATE: I just got this problem in Chrome. It work fine with Firefox and Edge
Setting setChunkedTransferEncoding should make it work.
In the code before the response is sent set:
response.setChunkedTransferEncoding(true);

H264 to PES packetization

I have Ti DaVinci h264 encoder and I want to pack its output frames to PES. The stream is in annex B format.
I took the ffmpeg's pes header writer and made something like this:
void MediaPacket::writePesHeader(std::vector< uint8_t >& buffer)
{
int header_len, flags, len, val;
uint8_t *q = buffer.data();
*q++ = 0x00;
*q++ = 0x00;
*q++ = 0x01;
*q++ = 0xe0;
header_len = 0;
flags = 0;
if (pts != UNKNOWN) {
header_len += 5;
flags |= 0x80;
}
if (dts != UNKNOWN && pts != UNKNOWN && dts != pts) {
header_len += 5;
flags |= 0x40;
}
len = 0;
*q++ = len >> 8;
*q++ = len;
val = 0x80;
*q++ = val;
*q++ = flags;
*q++ = header_len;
if (pts != UNKNOWN) {
write_pts(q, flags >> 6, pts);
q += 5;
}
if (dts != UNKNOWN && pts != UNKNOWN && dts != pts) {
write_pts(q, 1, dts);
q += 5;
}
buffer.resize(q-buffer.data());
}
static void write_pts(uint8_t *q, int fourbits, int64_t pts)
{
int val;
val = fourbits << 4 | (((pts >> 30) & 0x07) << 1) | 1;
*q++ = val;
val = (((pts >> 15) & 0x7fff) << 1) | 1;
*q++ = val >> 8;
*q++ = val;
val = (((pts) & 0x7fff) << 1) | 1;
*q++ = val >> 8;
*q++ = val;
}
Encoder's output without headers is played fine with Totem player and avplay, but there is an error "could not find codec parameters" when headers are presented.
What am I doing wrong?

Substitute an instruction depending on a condition

I have two for loops that I want to write in a function as one. The problem is that it differ only in one instruction
for (int i = 1; i <= fin_cabecera - 1 ; i++ ){
buffer[i] &= 0xfe;
if (bitsLetraRestantes < 0) {
bitsLetraRestantes = 7;
mask = 0x80;
letra = sms[++indiceLetra]; //*differs here*
}
char c = (letra & mask) >> bitsLetraRestantes--;
mask >>= 1;
buffer[i] ^= c;
}
And the other
for (int i = datos_fichero; i <= tamanio_en_bits + datos_fichero; i++){
buffer[i] &= 0xfe;
if (bitsLetraRestantes < 0) {
bitsLetraRestantes = 7;
mask = 0x80;
f.read(&letra, 1); //*differs here*
}
char c = (letra & mask) >> bitsLetraRestantes--;
mask >>= 1;
buffer[i] ^= c;
}
I thought in something like this:
void write_bit_by_bit(unsigned char buffer[], int from, int to, bool type) {
for (int i = to; i <= from; i++) {
buffer[i] &= 0xfe;
if (bitsLetraRestantes < 0) {
bitsLetraRestantes = 7;
mask = 0x80;
type ? (letra = sms[++indiceLetra]) : f.read(&letra, 1);
}
char c = (letra & mask) >> bitsLetraRestantes--;
mask >>= 1;
buffer[i] ^= c;
}
}
But I think there has to be a better method.
Context:
I will give more context (I will try explain it as better as I can within my language limitations). I have to read one byte each time because The Buffer variable represents a image pixel. sms is a message that have to be hidden within the image, and letra is a single char of that message. In order to not modify the aspect of the image, each bit of each character have to be written in the last bit of each pixel. Let me give you and example.
letra = 'H' // 01001000 in binary
buffer[0] = 255 // white pixel 11111111
In order to hide the H char, I will need 8 pixel:
The result will be like:
buffer[0] //11111110,
buffer[1] //11111111
buffer[2] //11111110
buffer[3] //11111110
buffer[4] //11111111
buffer[5] //11111110
buffer[6]//11111110
buffer[7]//11111110
The H is hidden in the last bit of the image. I hope I explained well.
[Solution]
Thanks to #anatolyg I've rewrited the code and now works just as I wanted. Here is how it looks:
void write_bit_by_bit(unsigned char buffer[], ifstream& f,int from, int to, char sms[], bool type){
unsigned short int indiceLetra = 0;
short int bitsLetraRestantes = 7;
unsigned char mask = 0x80; //Empezamos por el bit más significativo (10000000)
char* file_buffer;
if(type){ //Write file data
int number_of_bytes_to_read = get_file_size(f);
file_buffer = new char[number_of_bytes_to_read];
f.read(file_buffer, number_of_bytes_to_read);
}
const char* place_to_get_stuff_from = type ? file_buffer : sms;
char letra = place_to_get_stuff_from[0];
for (int i = from; i <= to; i++) {
buffer[i] &= 0xfe; //hacemos 0 último bit con máscara 11111110
//TODO: Hacer con dos for
if (bitsLetraRestantes < 0) {
bitsLetraRestantes = 7;
mask = 0x80;
letra = place_to_get_stuff_from[++indiceLetra];//letra = sms[++indiceLetra];
}
char c = (letra & mask) >> bitsLetraRestantes--;
mask >>= 1;
buffer[i] ^= c; //Almacenamos en el ultimo bit del pixel el valor del caracter
}
}
int ocultar(unsigned char buffer[],int tamImage, char sms[], int tamSms){
ifstream f(sms);
if (f) {
strcpy(sms,basename(sms));
buffer[0] = 0xff;
int fin_cabecera = strlen(sms)*8 + 1;
buffer[fin_cabecera] = 0xff;
write_bit_by_bit(buffer, f, 1, fin_cabecera -1, sms, WRITE_FILE_NAME);
int tamanio_en_bits = get_file_size(f) * 8;
int datos_fichero = fin_cabecera + 1;
write_bit_by_bit(buffer, f, datos_fichero, tamanio_en_bits + datos_fichero, sms, WRITE_FILE_DATA);
unsigned char fin_contenido = 0xff;
short int bitsLetraRestantes = 7;
unsigned char mask = 0x80;
for (int i = tamanio_en_bits + datos_fichero + 1;
i < tamanio_en_bits + datos_fichero + 1 + 8; i++) {
buffer[i] &= 0xfe;
char c = (fin_contenido & mask) >> bitsLetraRestantes--;
mask >>= 1;
buffer[i] ^= c;
}
}
return 0;
}
Since you are talking about optimization here, consider performing the read outside the loop. This will be a major optimization (reading 10 bytes at once must be quicker than reading 1 byte 10 times). This will require an additional buffer for (the file?) f.
if (!type)
{
char f_buffer[ENOUGH_SPACE];
number = calc_number_of_bytes_to_read();
f.read(f_buffer, number);
}
for (...) {
// your code
}
After you have done this, your original question is easy to answer:
const char* place_to_get_stuff_from = type ? sms : f_buffer;
for (...) {
...
letra = place_to_get_stuff_from[++indiceLetra];
...
}