Received Data Zeroed Out After Encountering First Byte Equal to Zero - raspberry-pi

Summarize the Problem:
I wrote a userspace SPI driver in linux for the NRF24L01+ transceiver. My goal is to send files to a server. A jetson nano is the sender, and a raspberry pi 3b+ the receiver. Both the spi and nano are running Linux.
I can consistently send packets and receive acknowledgements.
However, the issue is whenever I send a packet such as 0x ff ee dd 00 cc bb aa the receiver only receives the packet 0x ff ee dd 00 00 00 00. So what is happening is that whenever the first byte encountered is zero, the rest of the packet becomes zero. This causes the files I send to become corrupted.
I was able to reproduce this bug with a char array having a similar pattern. I noticed this trend when I printed out the file contents I was sending on the transmitter and receiver.
What I've tried:
I've tried altering my SPI read function. What I thought was happening was the chip select line was being flipped high early. This did not work, I got the same results.
I've printed the packets before calling the ioctl() function from the transmitter and the packet remains intact.
I've printed the return value of the ioctl() function to see how many bytes I was receiving and sending. I was sending 31 bytes from the transmitter, and receiving 32 bytes from the receiver. So it doesn't look like my reads and sends are failing.
If I had a logic analyzer my next step would be to check the SPI pins on the transmitter, but unfortunately I don't have one.
I've added a 10uF decoupling capacitor on the transceivers and that sped up communication.
Show Some Code:
Receiver side:
/**
* Reads the payload when data pipe
* is available.
*
* spi_dev_fd: file descriptor for spi device.
* */
int nrf_rx_read(int spi_dev_fd, char * payload, int * pipe, int * bytes)
{
int pipe_temp, rtn;
// TODO: Add timeout.
do
{
rtn = nrf_rx_pipe_available(spi_dev_fd, &pipe_temp);
}while(rtn != 0);
if(rtn == 0)
{
char status;
if(bytes != NULL)
{
char size;
spi_read_msg(spi_dev_fd, R_RX_PL_WID, &status, &size, 1);
*bytes = (int) size;
}
spi_read_msg(spi_dev_fd, R_RX_PAYLOAD , &status, payload, (int) NUM_PAYLOAD_BYTES);
*pipe = pipe_temp;
char msg;
msg = RX_DR;
spi_send_msg(spi_dev_fd, W_REGISTER | STATUS, &msg, 1);
return 0;
}
return 1;
}
bool nrf_rx_pipe_available(int spi_dev_fd, int * pipe)
{
char addr = NOP;
char status;
spi_read_msg(spi_dev_fd, addr, &status, NULL, 0);
if((status & RX_DR) > 0)
{
*pipe = (status >> RX_P_NO) & 0x07;
if(*pipe > 5)
{
return 1;
}
return 0;
}
return 1;
}
int spi_read_msg(int spi_dev_fd, char addr, char * status, char * copy_to, int len)
{
char data_buffer;
char recv_buffer[len + 1];
struct spi_ioc_transfer xfer;
memset(&xfer, 0, sizeof(xfer));
memset(&recv_buffer, 0, sizeof(recv_buffer));
data_buffer = addr;
xfer.tx_buf = (unsigned long) &data_buffer;
xfer.rx_buf = (unsigned long) recv_buffer;
xfer.len = len + 2;
xfer.bits_per_word = 8;
xfer.speed_hz = 1000000;
xfer.cs_change = 0;
xfer.rx_nbits = len * 8;
xfer.tx_nbits = 8;
int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);
if(res > 0)
{
status[0] = recv_buffer[0];
if(copy_to != NULL)
{
string temp = string(recv_buffer);
temp = temp.substr(1);
strncpy(copy_to, temp.c_str(), len);
}
// debug code
for(int i = 0; i < len; ++i)
{
printf("copy_to: %x \n ", copy_to[i]);
}
// end debug code.
}
return res;
}
Transmitter side:
/**
* Function to load a payload and send a packet.
*
*
* spi_dev_fd: file descriptor for spi device.
* */
int nrf_tx_send_packet(int spi_dev_fd, char * payload, int len)
{
int rtn;
// Put low so we can add the payload.
gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_LOW);
// Set a new payload.
nrf_tx_new_payload(spi_dev_fd, payload, len);
// Start tx transmission.
gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_HIGH);
do
{
rtn = nrf_tx_pending_send(spi_dev_fd);
if(rtn == 2)
{
char clr = MAX_RT;
spi_send_msg(spi_dev_fd, W_REGISTER | STATUS, &clr, 1);
}
}while(rtn != 1);
// Go back to standby mode
gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_LOW); // Setting chip enable to 0.
char reg = W_REGISTER | STATUS;
char val = RX_DR | TX_DS | MAX_RT;
spi_send_msg(spi_dev_fd, reg, &val, 1);
return 0;
}
int spi_send_msg(int spi_dev_fd, char addr, char * data, int len)
{
char data_buffer[len + 1];
char recv_buffer;
struct spi_ioc_transfer xfer;
memset(&xfer, 0, sizeof(xfer));
memset(&recv_buffer, 0, sizeof(recv_buffer));
data_buffer[0] = addr;
for(int i = 1; i < len + 1; ++i)
{
data_buffer[i] = data[i-1];
printf("databuffer[i]: %x \n", data_buffer[i]);
}
xfer.tx_buf = (unsigned long) data_buffer;
xfer.rx_buf = (unsigned long) NULL;
xfer.len = len + 1;
xfer.bits_per_word = 8;
xfer.speed_hz = 1000000;
xfer.cs_change = 0;
//xfer.rx_nbits = 8;
xfer.rx_nbits = 0;
xfer.tx_nbits = (8 * len) + 8;
int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);
printf("res: %i \n", res);
return res;
}
I tried to add all the relevant code, sorry if it is a bit much. Main thing to look at is the send and receive functions. They all work as expected until I encounter the zeroed out byte.
If I am missing any information that can help someone out please let me know and I can add it. I think the send and receive functions are the most important however. I'm able to set and read the registers of the transceiver.

I can send files now!
The fix was done in spi_read_msg() function.
The problem was I was converting the buffer received to a string, which caused the data to be trimmed when the byte 0x00 was encountered. This is also equivalent to the null terminating character.
Receiver code:
int spi_read_msg(int spi_dev_fd, char addr, char * status, char * copy_to, int len)
{
char data_buffer;
char recv_buffer[len + 1];
struct spi_ioc_transfer xfer;
memset(&xfer, 0, sizeof(xfer));
memset(&recv_buffer, 0, sizeof(recv_buffer));
data_buffer = addr;
xfer.tx_buf = (unsigned long) &data_buffer;
xfer.rx_buf = (unsigned long) recv_buffer;
xfer.len = len + 2;
xfer.bits_per_word = 8;
xfer.speed_hz = 1000000;
xfer.cs_change = 0;
xfer.rx_nbits = len * 8;
xfer.tx_nbits = 8;
int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);
if(res > 0)
{
status[0] = recv_buffer[0];
if(copy_to != NULL)
{
for(int i = 0; i < len; ++i)
{
copy_to[i] = recv_buffer[i + 1];
}
}
}
return res;
}

Related

BMP File to PNG File Converter

I'm making a BMP to PNG Converter.
The BMP Images are uncompressed.
So my question is when the BMP File is converted to a PNG File, then is the PNG File compressed i.e is the image data compressed. If so how is the image data aligned in the PNG File Format?
If the PNG Image Data is uncompressed then how is the BMP Image Data Aligned in PNG File.
#include<stdio.h>
#include<stdlib.h>
#pragma pack(1)
typedef struct
{
unsigned short int st_m40_FileType;
unsigned int st_m40_ImgFileSize;
unsigned short int st_m40_RsvdBytes1;
unsigned short int st_m40_RsvdBytes2;
unsigned int st_m40_ImgDataOffset;
unsigned int st_m40_Info40HeaderSze;
int st_m40_PxWdth;
int st_m40_PxHeight;
unsigned short int st_m40_NumOfColrPlnes;
unsigned short int st_m40_BitsPerPixel;
unsigned int st_m40_CmprsnType;
unsigned int st_m40_AftrCmprsnImgDataSze;
int st_m40_xResolutn_ppm;
int st_m40_yResolutn_ppm;
unsigned int st_m40_NumOfColrTbleColrs;
unsigned int st_m40_NumOfImprtntColrs;
}ST_BMP40HEADER_t;
typedef struct
{
ST_BMP40HEADER_t st_mBMP40MainHdrVar;
unsigned char * pst_mImgeData;
}ST_IMAGE_40_HEADER_t;
typedef enum
{
BI_RGB = 0x00,
BI_RLE8,
BI_RLE4,
BI_BITFIELDS,
BI_JPEG,
BI_PNG,
BI_ALPHABITFIELDS,
BI_CMYK,
BI_CMYKRLE8,
BI_CMYKRLE4,
}EN_BMP_COMPRESN_TYPE_t;
#pragma pack(1)
typedef struct
{
int st_mImgWdth;
int st_ImgHeight;
unsigned char st_mBitDepth;
unsigned char st_mColorType;
unsigned char st_mCmprsnMthd;
unsigned char st_mFltrMthd;
unsigned char st_mInterlaceMthd;
}ST_IHDR_DATA_FIELDS_t;
#pragma pack(1)
typedef struct
{
unsigned int st_mChunkDataLngth;
unsigned char st_mChunkType[4];
ST_IHDR_DATA_FIELDS_t st_IHDR_DataFieldsVar;
unsigned int st_mCRC32CheckSum;
}ST_IHDR_t;
#pragma pack(1)
typedef struct
{
unsigned int st_mPLTE_ChunkDataLngth;
unsigned char st_mPLTE_ChunkType[4];
unsigned char* st_mPLTE_ChunkDataPtr;
unsigned int st_mPLTE_CRC32CheckSum;
}ST_PLTE_t;
#pragma pack(1)
typedef struct
{
unsigned int st_mIDAT_ChunkDataLngth;
unsigned char st_mIDAT_ChunkType[4];
unsigned char* st_mIDAT_ChunkDataPtr;
unsigned int st_mIDAT_CRC32CheckSum;
}ST_IDAT_t;
#pragma pack(1)
typedef struct
{
unsigned int st_mIEND_ChunkDataLength;
unsigned char st_mIEND_ChunkType[4];
unsigned char * st_mIEND_ChunkDataPtr;
unsigned int st_mIEND_CRC32CheckSum;
}ST_IEND_t;
/* Little Endian to Big-Endian API. */
unsigned int BMP2PNG_LitToBigEndian(unsigned int f_BigEndianVal)
{
return (((f_BigEndianVal>>24) & 0x000000ff) | ((f_BigEndianVal>>8) & 0x0000ff00) |\
((f_BigEndianVal<<8) & 0x00ff0000) | ((f_BigEndianVal<<24) & 0xff000000));
}
/* CRC32 API.*/
unsigned int BMP2PNG_CmputeCRC32(unsigned char *p_fIpVal, unsigned int f_IpSize)
{
int l_LoopVar;
unsigned int l_ByteVal, l_CRCVal, l_MaskVal;
unsigned int l_TmpIncVar = 0;
l_CRCVal = 0xFFFFFFFF;
while (l_TmpIncVar <= f_IpSize)
{
// Get next byte.
l_ByteVal = p_fIpVal[l_TmpIncVar];
l_CRCVal = l_CRCVal ^ l_ByteVal;
for (l_LoopVar = 7; l_LoopVar >= 0; l_LoopVar--)
{
// Do eight times.
l_MaskVal = -(l_CRCVal & 1);
l_CRCVal = (l_CRCVal >> 1) ^ (0xEDB88320 & l_MaskVal);
}
l_TmpIncVar = l_TmpIncVar + 1;
}
return ~l_CRCVal;
}
/* API converts BMP-to-PNG format. */
char * Convert__40_BMP2PNG(ST_IMAGE_40_HEADER_t * pst_fBMP40ImgHdrVar, FILE * p_ImgFilePtr,\
unsigned char * p_fBMP_ColrTble)
{
FILE * l_BMP2PNGFilePtr;
ST_IHDR_t * pst_lIHDRChunkVar;
unsigned char l_PNGSignature[8]={137, 80, 78, 71, 13, 10, 26, 10};
unsigned int l_BigEndianVal;
unsigned int l_CRC32Val;
unsigned char * l_TempCRCBuff;
unsigned char * l_CRCBuffer;
unsigned int l_BuffLength = 0;
unsigned int l_TempIHDRChunkDataLngth;
pst_lIHDRChunkVar = (ST_IHDR_t *) malloc(sizeof(*pst_lIHDRChunkVar));
l_BMP2PNGFilePtr = fopen("BMP2PNG2.png","w");
/* Writing the 1st 8-bytes to the PNG File.*/
fwrite(l_PNGSignature,1,8,l_BMP2PNGFilePtr);
fseek(l_BMP2PNGFilePtr,8,SEEK_SET);
pst_lIHDRChunkVar->st_mChunkDataLngth = 13;
l_TempIHDRChunkDataLngth = BMP2PNG_LitToBigEndian(13);
/*Writing the IHDR Chunk Data-Length-Size value to the file.*/
fwrite(&l_TempIHDRChunkDataLngth,sizeof(unsigned int),1,l_BMP2PNGFilePtr);
pst_lIHDRChunkVar->st_mChunkType[0] = 'I';
pst_lIHDRChunkVar->st_mChunkType[1] = 'H';
pst_lIHDRChunkVar->st_mChunkType[2] = 'D';
pst_lIHDRChunkVar->st_mChunkType[3] = 'R';
/* Writing the IHDR-Chunk-Type value to the file.*/
fwrite( pst_lIHDRChunkVar->st_mChunkType ,sizeof(unsigned char),4,l_BMP2PNGFilePtr);
// pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth = BMP2PNG_LitToBigEndian(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth);
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth = BMP2PNG_LitToBigEndian(3);
// pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight = BMP2PNG_LitToBigEndian(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight);
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight = BMP2PNG_LitToBigEndian(3);
if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel <= 8)
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mBitDepth = pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel;
}
else if( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 24) || \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 32) )
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mBitDepth = 8;
}
else
{
/*No Action.*/
}
if( pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel <=8 )
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mColorType = 3;
}
else if (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 24)
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mColorType = 2;
}
else if (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 32)
{
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mColorType = 6;
}
else
{
/*No Action.*/
}
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mCmprsnMthd = 0;
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mFltrMthd = 0;
pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mInterlaceMthd = 0;
fseek(l_BMP2PNGFilePtr,16,SEEK_SET);
fwrite(&pst_lIHDRChunkVar->st_IHDR_DataFieldsVar,sizeof(ST_IHDR_DATA_FIELDS_t),1,l_BMP2PNGFilePtr);
{
/* Framing the data for calculating the 32-bit CRC Checksum.*/
l_BuffLength = 4+(pst_lIHDRChunkVar->st_mChunkDataLngth);
l_CRCBuffer = (unsigned char*)malloc(l_BuffLength);
l_TempCRCBuff = l_CRCBuffer;
*l_TempCRCBuff++ = pst_lIHDRChunkVar->st_mChunkType[0];
*l_TempCRCBuff++ = pst_lIHDRChunkVar->st_mChunkType[1];
*l_TempCRCBuff++ = pst_lIHDRChunkVar->st_mChunkType[2];
*l_TempCRCBuff++ = pst_lIHDRChunkVar->st_mChunkType[3];
*l_TempCRCBuff++ = (unsigned char)pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth;
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth << 8);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth << 16);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mImgWdth << 24);
*l_TempCRCBuff++ = (unsigned char)pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight;
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight << 8);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight << 16);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_ImgHeight << 24);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mBitDepth);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mColorType);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mCmprsnMthd);
*l_TempCRCBuff++ = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mFltrMthd);
*l_TempCRCBuff = (unsigned char)(pst_lIHDRChunkVar->st_IHDR_DataFieldsVar.st_mInterlaceMthd);
// Compute and output CRC
l_CRC32Val = BMP2PNG_CmputeCRC32(l_CRCBuffer, l_BuffLength);
l_CRC32Val = BMP2PNG_LitToBigEndian( l_CRC32Val);
fseek(l_BMP2PNGFilePtr,29,SEEK_SET);
unsigned int returnVal = fwrite(&l_CRC32Val,sizeof(unsigned int),1,l_BMP2PNGFilePtr);
}
unsigned char * p_lBMPImgData = pst_fBMP40ImgHdrVar->pst_mImgeData;
// unsigned int l_BMPImgeDataSze = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) );
unsigned int l_BMPImgeDataSze = (3*3)*3;
ST_IDAT_t * pst_lIDAT_ChunkVar;
pst_lIDAT_ChunkVar = (ST_IDAT_t *) malloc(sizeof(*pst_lIDAT_ChunkVar));
unsigned int l_ImgDataSzeIncVar = 0;
unsigned char * p_IDATBuf;
unsigned char * p_TempIDATBuf;
unsigned int l_IDATBufSze;
if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 24)
{
fseek(l_BMP2PNGFilePtr,33,SEEK_SET);
l_BMPImgeDataSze *= 3;
l_IDATBufSze = 4 + l_BMPImgeDataSze;
p_IDATBuf = (unsigned char*)malloc(l_IDATBufSze);
p_TempIDATBuf = p_IDATBuf;
pst_lIDAT_ChunkVar->st_mIDAT_ChunkDataLngth = BMP2PNG_LitToBigEndian(l_BMPImgeDataSze);
fwrite(&pst_lIDAT_ChunkVar->st_mIDAT_ChunkDataLngth,sizeof(unsigned int),1,l_BMP2PNGFilePtr);
pst_lIDAT_ChunkVar->st_mIDAT_ChunkType[0] = 'I';
pst_lIDAT_ChunkVar->st_mIDAT_ChunkType[1] = 'D';
pst_lIDAT_ChunkVar->st_mIDAT_ChunkType[2] = 'A';
pst_lIDAT_ChunkVar->st_mIDAT_ChunkType[3] = 'T';
fwrite( pst_lIDAT_ChunkVar->st_mIDAT_ChunkType ,sizeof(unsigned char),4,l_BMP2PNGFilePtr);
fseek(l_BMP2PNGFilePtr,41,SEEK_SET);
unsigned char ImgeData[27] = { 0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,};
while(l_ImgDataSzeIncVar <= l_BMPImgeDataSze )
{
fwrite(ImgeData,sizeof(unsigned char),1,l_BMP2PNGFilePtr);
/*
fwrite( (p_lBMPImgData+2),sizeof(unsigned char),1,l_BMP2PNGFilePtr);
*p_TempIDATBuf++ = *(p_lBMPImgData+2);
fwrite( (p_lBMPImgData+1),sizeof(unsigned char),1,l_BMP2PNGFilePtr);
*p_TempIDATBuf++ = *(p_lBMPImgData+1);
fwrite( (p_lBMPImgData),sizeof(unsigned char),1,l_BMP2PNGFilePtr);
*p_TempIDATBuf++ = *(p_lBMPImgData);
p_lBMPImgData += 3;
l_ImgDataSzeIncVar += 3;
*/
}
// Compute and output CRC
unsigned int crc32 = BMP2PNG_CmputeCRC32(p_IDATBuf, l_IDATBufSze);
fwrite(&crc32,sizeof(unsigned int),1,l_BMP2PNGFilePtr);
}
}
ST_IMAGE_40_HEADER_t * ReadBMP40HdrImage(ST_IMAGE_40_HEADER_t * pst_fBMP40ImgHdrVar, \
FILE * p_ImgFilePtr)
{
unsigned short int l_ColorTbleSze;
unsigned char * l_ColorTbleVal;
unsigned int l_ImageDataOffset;
unsigned int l_ImageDataSize;
unsigned int l_ImageDataSzeIncVar = 1;
unsigned char * l_ImageDataPtr;
unsigned int l_PixelCount = 1;
int l_NumOfReadBlks = fread(pst_fBMP40ImgHdrVar,sizeof(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar),1,p_ImgFilePtr);
printf("\n********************************************************************\n");
printf("\nPrinting the BMP Image Parameters:\n");
printf("\nBMP File Header Parameters.\n");
printf("File Type:\t'BM'\n");
printf("Total Size of the image:\t%u\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_ImgFileSize);
printf("Image Data Offset:\t%u\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_ImgDataOffset);
printf("\nBMP Info Header Parameters.\n");
printf("Size of the Info-Header:\t'%u-Bytes'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_Info40HeaderSze);
printf("Width of the BMP Image:\t'%d-Pixels'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth);
printf("Height of the BMP Image:\t'%d-Pixels'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight);
printf("Number of Color Planes:\t'%d'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrPlnes);
printf("Number of Bits-Per-Pixel:\t'%d'.\n",pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel);
printf("Compression Type used for compressing the BMP Raw Image:\t'%d'.\n",\
pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_CmprsnType);
printf("Horizontal Resolution:\t'%d-Pixels Per Meter'.\n,",\
pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_xResolutn_ppm);
printf("Vertical Resolution:\t'%d-Pixels Per Meter'.\n,",\
pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_yResolutn_ppm);
if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrTbleColrs !=0 )
{
printf("Number of Colors in the color table:\t'%u'.\n",\
pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrTbleColrs);
}
if( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel <= 8) && \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrTbleColrs !=0) )
{
rewind(p_ImgFilePtr);
fseek(p_ImgFilePtr,55,SEEK_SET);
l_ColorTbleSze = (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_NumOfColrTbleColrs) * 4 ;
l_ColorTbleVal = (unsigned char*) malloc( l_ColorTbleSze );
l_NumOfReadBlks = fread(l_ColorTbleVal, l_ColorTbleSze, 1, p_ImgFilePtr);
if(l_NumOfReadBlks <1)
{
printf("Couldn't read the Color-Table values from the BMP File.\n");
return NULL;
}
else if(l_NumOfReadBlks == 1)
{
unsigned short int l_ClrTbleIncVar = 0;
unsigned char * l_TempColorTbleVal = l_ColorTbleVal;
unsigned short int l_IndexVal = 0;
printf("\n*****************************************************************************\n");
printf("Printing the color Table.\n");
while (l_ClrTbleIncVar <= (l_ColorTbleSze-4) )
{
printf("Index '%d' : ", l_IndexVal);
printf("Blue -> '%d'\t",*l_TempColorTbleVal);
l_TempColorTbleVal++;
printf("Green -> '%d'\t",*l_TempColorTbleVal);
l_TempColorTbleVal++;
printf("Red -> '%d'\t\n",*l_TempColorTbleVal);
l_TempColorTbleVal+=2;
l_ClrTbleIncVar += 4;
l_IndexVal++;
}
}
}
rewind(p_ImgFilePtr);
l_ImageDataOffset = pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_ImgDataOffset;
fseek(p_ImgFilePtr,l_ImageDataOffset,SEEK_SET);
if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 4)
{
l_ImageDataSize = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) )/2;
pst_fBMP40ImgHdrVar->pst_mImgeData = (unsigned char*)malloc(l_ImageDataSize);
l_ImageDataPtr = pst_fBMP40ImgHdrVar->pst_mImgeData;
l_NumOfReadBlks = fread(l_ImageDataPtr,1,l_ImageDataSize,p_ImgFilePtr);
if(l_NumOfReadBlks < 1)
{
printf("Couldn't read the image data from the file.\n");
return NULL;
}
}
else if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 8)
{
l_ImageDataSize = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) );
pst_fBMP40ImgHdrVar->pst_mImgeData = (unsigned char*)malloc(l_ImageDataSize);
l_ImageDataPtr = pst_fBMP40ImgHdrVar->pst_mImgeData;
l_NumOfReadBlks = fread(l_ImageDataPtr,l_ImageDataSize,1,p_ImgFilePtr);
if(l_NumOfReadBlks < 1)
{
printf("Couldn't read the image data from the file.\n");
return NULL;
}
}
else if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 24)
{
l_ImageDataSize = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) * 3 );
pst_fBMP40ImgHdrVar->pst_mImgeData = (unsigned char*)malloc(l_ImageDataSize);
l_ImageDataPtr = pst_fBMP40ImgHdrVar->pst_mImgeData;
l_NumOfReadBlks = fread(l_ImageDataPtr,l_ImageDataSize,1,p_ImgFilePtr);
if(l_NumOfReadBlks < 1)
{
printf("Couldn't read the image data from the file.\n");
return NULL;
}
}
else if(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_BitsPerPixel == 32)
{
l_ImageDataSize = ( (pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxWdth) * \
(pst_fBMP40ImgHdrVar->st_mBMP40MainHdrVar.st_m40_PxHeight) * 4 );
pst_fBMP40ImgHdrVar->pst_mImgeData = (unsigned char*)malloc(l_ImageDataSize);
l_ImageDataPtr = pst_fBMP40ImgHdrVar->pst_mImgeData;
l_NumOfReadBlks = fread(l_ImageDataPtr,l_ImageDataSize,1,p_ImgFilePtr);
if(l_NumOfReadBlks < 1)
{
printf("Couldn't read the image data from the file.\n");
return NULL;
}
}
rewind(p_ImgFilePtr);
Convert__40_BMP2PNG(pst_fBMP40ImgHdrVar,p_ImgFilePtr,l_ColorTbleVal);
}
int main()
{
FILE * l_ImgeFilePtr;
l_ImgeFilePtr = fopen("FLAG_B24.BMP","r");
unsigned short int l_ImgeFileType;
unsigned int l_InfoHdrSze;
int l_NumofReadBlocks;
l_NumofReadBlocks = fread(&l_ImgeFileType,2,1,l_ImgeFilePtr);
if(l_NumofReadBlocks <1)
{
printf("Couldn't read the bytes from the file.\n");
return 0;
}
if(l_ImgeFileType != 19778)
{
printf("Image Passed is not a BMP file.\n");
return 0;
}
fseek(l_ImgeFilePtr,14,SEEK_SET);
l_NumofReadBlocks = fread(&l_InfoHdrSze, 4, 1, l_ImgeFilePtr);
if(l_NumofReadBlocks <1)
{
printf("Couldn't read the bytes from the file.\n");
return 0;
}
rewind(l_ImgeFilePtr);
if( l_InfoHdrSze == 40 )
{
ST_IMAGE_40_HEADER_t * pst_Img40HdrVar;
pst_Img40HdrVar = malloc(sizeof(*pst_Img40HdrVar));
if(pst_Img40HdrVar == NULL)
{
printf("There isn't enough memory to allocate for the Image header variable.\n");
return 0;
}
ST_IMAGE_40_HEADER_t * pst_l40_ReadAPIReturnVal = ReadBMP40HdrImage(pst_Img40HdrVar, l_ImgeFilePtr);
}
}
is the PNG File compressed
Yes.
how is the image data aligned in the PNG File Format?
It's not aligned. From the spec, "The chunk data length may be any number of bytes up to the maximum; therefore, implementors cannot assume that chunks are aligned on any boundaries larger than bytes."
Multitudinous image handling libraries exist to save you from worrying about these details, though. I'd recommend against rolling your own converter unless your goal is specifically to learn about image file formats.

low cpu-usage way to monitor connection to localhost

It seems a nonblocking connect to localhost always fails right away then poll() returns immediately with POLLIN flag set in revents. That prevents CPU enter a blocking state and the entire system runs in quite high cpu usage.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1470 panruoc+ 20 0 12956 1956 1820 S 26.2 0.0 2:09.49 zz1
Any suggestion is appriciated.
Here is my code of testing
int main(int argc, char *argv[])
{
struct sockdesc {
char *host;
int port;
int sockfd;
};
struct sockdesc sdes[] = {
{"localhost", 6000},
{"111.206.239.212", 6000},
};
unsigned int i;
for(i = 0; i < 2; i++) {
tcp_connect(sdes[i].host, sdes[i].port, &sdes[i].sockfd);
printf("sockfd = %d, %d\n", sdes[i].sockfd, errno);
}
if(!nonblocking)
return 0;
struct pollfd pollfds[2];
pollfds[0].fd = sdes[0].sockfd;
pollfds[1].fd = sdes[1].sockfd;
pollfds[0].events = POLLIN;
pollfds[1].events = POLLIN;
int conns;
for(conns = 0; conns != 3; ) {
int nfds = poll(pollfds, 2, -1);
if(nfds <= 0)
exit(1);
for(i = 0; (int)i < nfds; i++) {
if(pollfds[i].revents) {
if(pollfds[i].revents & POLLIN)
conns |= i;
printf(" fd = %d, revents = 0x%04x\n", sdes[i].sockfd, pollfds[i].revents);
}
}
}
return 0;
}
BR, Ruochen
Your for-loop looks suspicious:
for(conns = 0; conns != 3; ) {
When does conns ever become three?
It seems like your intent is here:
if(pollfds[i].revents & POLLIN)
conns |= i;
But if i is 0 for the first socket, conns |= i will not change the value.
And when both sockets have data available, your poll call will start returning immediately, but you are stuck in an infinite loop. Hence, high cpu overhead.
It appears your code's intent is to stay in a loop until both sockets have data available to read. Then break out of the loop then. So I suspect you really meant this:
conns |= (i+1);
There's other problems as well. poll returns the number of valid socket descriptors. Hence this line;
for(i = 0; (int)i < nfds; i++) {
So if the socket associated with pollfds[1] has data available, nfds will only be 1. Hence, your loop will only evaluate if pollfds[0] has data.
Let's clean your code up:
int ready_set = 0x00;
int all_ready_set = 0x03;
int num_sockets = 2;
while (ready_set != all_ready_set)
{
int nfds = poll(pollfds, 2, -1);
if(nfds <= 0)
{
// I would not actually exit. If a socket gets closed locally, you would have a valid and expected error, but maybe that can't happen in your program
exit(1);
}
for (i = 0; i < num_sockets; i++)
{
if (pollfds[i].revents & POLLIN)
{
int mask = 0x01 << i;
pollfds[i].events = 0; // stop listening for events on this socket
ready_set |= mask;
}
}
}

Go back N protocol implememtation

I am implementing Go back N protocol in C.I keep a char buffer and append the header informationa and data and send it to the server from the client process.
When I keep window size less than 10, the sequence number takes the value 1-9and occupies only one byte in the buffer. When the window size is >= 10 , sequence number may 1 or 2 bytes in the character array. So I am appending length of sequence number also as a header information. That time I am getting some random data written in the output file at the server. Whereas for window size less than 10 I coded without adding sequence no. length info. Everything works fine that time.
The codes are quiet exhaustive. Yet,
Can anybody suggest any corrections to be made in the code?
client code for window size 10:-
#include<stdio.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<netdb.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<time.h>
#include<sys/time.h>
unsigned short int checksum_2(void *buffer,unsigned int len,unsigned short int seed)
{
unsigned char *buf1 = (unsigned char*)buffer;
int i;
for(i=0;i<len;i++)
{
seed+=(unsigned int)(*buf1++);
}
//fold 32-bit sum to 16 bit
while(seed>>16)
seed = (seed & 0xFFFF)+ (seed>>16);
return seed;
}
unsigned short int checksum(unsigned char * buff,unsigned int count)
{
register unsigned int sum = 0;
//main summing loop
while(count >1)
{
sum += *((unsigned short int*) buff);
(buff)++;
count = count -2;
}
//add left over byte if any
if(count>0)
{
sum += *((unsigned char *)buff);
}
//fold 32-bit sum to 16 bit
while(sum>>16)
sum = (sum & 0xFFFF)+ (sum>>16);
return (~sum);
}
char* rand_corrupt(unsigned char* buff)
{
int n = strlen(buff);
char* str_temp = (char*)calloc(1,n); //allocate memory for a string
int i;
int num;
num = rand() %100;
if(num>95)
{
for(i=0;i<strlen(buff);i++)
{
buff[i] = buff[i]+1;
}
}
strcpy(str_temp,buff);
return str_temp;
}
char *itoa(long i,char *s,int dummy_radix)
{
sprintf(s,"%ld",i);
return s;
}
void rand_wait()
{
int num;
int i;
num = rand() %100;
if(num<5)
{
for(i=0;i<10;i++)
{
sleep(1);
}
}
return;
}
int
main (int argc, char **argv)
{
int sock,length,n;
struct sockaddr_in server,from;
struct hostent *hp;
long int packets =0;
clock_t t; //to measure CPU time
struct timeval start,end; //to measure actual execution time
struct timeval timer; //for the timer implementation
double time_diff;//to measure the timer for the execution time of code
unsigned short int check;
void* buff;
printf("initializing 2 d array\n");
char buf[1024][1024]={0};
printf("initialisation failed\n");
int nread[1024] = {0,};
char new_buff[65535]={0, };
char ack_buf[65535]={0, };
char* temp;
char checksum_info[1024]={0, } ;
char bytes_info[1024] = {0, } ;
unsigned short int bytes_len;
char bytes_len_str[1024]={0, };
char seqnum[10] = {0,};
int seq_no;
char current;
char data_1[75535]={0, };
unsigned short int check_length;
char check_len_str[1024]={0, };
char ack_check_len[1024]={0, };
unsigned short int ack_checksum_len;
char ack_check[65535]={0, };
unsigned short int ack_checksum;
char temp_buf[65535]={0, };
char temp_buffer[655]={0,};
unsigned short int actual_checksum;
unsigned short int length1;
char content[65535]={0, };
int i,j;
char end_flag =0; //to mark the end of file or error occured while reading file
int total_len[1024]={0,};
char data[1024][6553]= {0,};
char *tmp = NULL;
int msec,trigger;
clock_t difference,initial;
char ack_seqlen_char[8]= {0,};
int ack_seqlen;
int ack_seq;
char ack_seq_char[10] ={0,};
int seqnum_len;
char seqlen_char[10] = {0,};
t = clock();
gettimeofday(&start,NULL);
buff = calloc(1,1024);//allocating memory for message buffer
if(buff == NULL)
{
printf("memory allocation failedi\n");
return 1;
}
temp = calloc(1,65535); //allocating memory for new message
if(temp == NULL)
{
printf("memory allocation failed\n");
return 1;
}
// checking if hostname and the port address is provided //
if(argc!=3)
{
printf("insufficient arguments\n");
exit(1);
}
//create a socket//
sock = socket(AF_INET,SOCK_DGRAM,0);
if(sock<0)
{
printf("error in opening socket\n");
return 1;
}
//to get the hostname of the system or the machine//
hp= gethostbyname(argv[1]);
if(hp==0)
{
printf("Unknown host\n");
return 1;
}
//build the server's IP address //
bzero((char *)&server,sizeof(server));
bcopy((char*)hp->h_addr,(char *)&server.sin_addr,hp->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[2]));
length = sizeof(server);
/*open the file that we wish to transfer*/
FILE *fp = fopen("alice.txt","rb");
if(fp==NULL)
{
printf("file open error");
return 1;
}
fseek(fp,0,SEEK_END); //if exists read the size of the file
size_t file_size = ftell(fp);
fseek(fp,0,SEEK_SET);
printf("size of the file is %d\n", file_size);
/*find the number of packets*/
if(file_size == 0)
{
packets = 0;
}
else
{
packets = (file_size/1024)+1 ;
}
/*send the number of packets to the server*/
itoa(packets,(char*)buff,10);
printf("packets =%s\n",(char*)buff);
n= sendto(sock,buff,1024,0,(struct sockaddr *)&server,sizeof(struct sockaddr));
if(n<0)
{
printf("error in sending message to the server");
return 1;
}
int loop =1;
/*Read data from file and send it*/
int packetNum = 0;
int N = 10;
int base = 1;
int nextseqnum =1;
int sequence;
int seqnum_next = 1;
while(1)
{
while(nextseqnum<base+N) //send N consecutive packets
{
memset(buf[nextseqnum], 0, 65535); //clear the contents of buf before fread
memset(seqnum,0,10);
memset(seqlen_char,0,10);
memset(checksum_info,0,1024);
memset(check_len_str,0,1024);
memset(bytes_info,0,1024);
memset(bytes_len_str,0,1024);
memset(data[nextseqnum],0,6553);
/*First read file in chunks of 1024 bytes */
nread[nextseqnum] = fread(buf[nextseqnum],1,1024,fp);
printf("Bytes read %d\n",nread[nextseqnum]);
/*if read was success ,send data*/
if(nread[nextseqnum]>0)
{
printf ("I am HERE\n");
check = checksum(buf[nextseqnum],nread[nextseqnum]); //calculate the checksum
printf("checksum is %d\n",check);
itoa(check,checksum_info,10); //convert checksum into string
check_length = strlen(checksum_info); //calculate the length of the checksum
itoa(check_length,check_len_str,10); //convert the checksum lenght to string form
itoa(nread[nextseqnum],bytes_info,10); //the data length in string format
bytes_len = strlen(bytes_info);
itoa(bytes_len,bytes_len_str,10);
itoa(seqnum_next,seqnum,10); //combine seq no,checksum and the data content into one packet
printf("sequence number is %s\n",seqnum);
seqnum_len = strlen(seqnum); //getting the length of the sequence
itoa(seqnum_len,seqlen_char,10); //converting it into string format
strncat(data[nextseqnum],seqlen_char,strlen(seqlen_char));
strncat(data[nextseqnum],seqnum,strlen(seqnum));
strncat(data[nextseqnum],check_len_str,(strlen(check_len_str)));
strncat(data[nextseqnum],checksum_info,(strlen(checksum_info))); //adding checksum
strncat(data[nextseqnum],bytes_len_str,strlen(bytes_len_str)); //adding data length
strncat(data[nextseqnum],bytes_info,strlen(bytes_info)); //adding the data length info
j= seqnum_len+3+bytes_len+check_length;
for(i=0;i<nread[nextseqnum];i++)
{
data[nextseqnum][j] = buf[nextseqnum][i];
j++;
}
total_len[nextseqnum] = nread[nextseqnum]+3+bytes_len+check_length;//finding the total length
data[nextseqnum][total_len[nextseqnum]] = '\0';
n= sendto(sock,data[nextseqnum],total_len[nextseqnum],0,(struct sockaddr *)&server,sizeof(struct sockaddr));///send the data packet after adding the header info
if(n<0)
{
printf("error in sending message to the server");
fclose(fp);
return 1;
}
if(nextseqnum == base)
{
msec = 0;
trigger = 50; /*50 ms*/
initial = clock(); /*start the timer*/
}
nextseqnum++;
seqnum_next = nextseqnum%N;
if(seqnum_next == 0)
{
seqnum_next = N;
}
sleep(1);
}
/*There is something tricky going on with the read..
* Either there was error ,or we reached end of file.
*/
else
{
if(feof(fp))
printf("End of file\n");
if(ferror(fp))
printf("Error reading\n");
end_flag = 1; //set the flag that it has reached EOF or encountered error
break;
}
}
while(1) //wait for the acknowledgement for the sent packets till timeout , here timer value is set to 50 ms
{
difference = clock()-initial;
msec = difference*1000/CLOCKS_PER_SEC;
if(msec<trigger) //if it is not timeout then receive the ack packets
{
memset(ack_buf, 0, 65535); //clear the contents of ack_buf
memset(ack_check_len,0,1024);
memset(ack_check,0,65535);
memset(content,0,65535);
memset(temp_buf,0,65535);
//printf ("Receiving packet\n");
n = recvfrom(sock,ack_buf,1024,MSG_DONTWAIT,&server, &length); //receive the ack from the server
if(n>0)
{
j=0;
for(i=0;i<1;i++)
{
temp_buffer[j] = ack_buf[i];
j++;
}
temp_buffer[j] = '\0';
strcpy(ack_seqlen_char,temp_buffer);//get the length of the ack sequence //number
ack_seqlen = atoi(ack_seqlen_char); //converting it to int
j=0;
for(i=1;i<1+ack_seqlen;i++)
{
ack_seq_char[j]= ack_buf[i];
j++; //next bytes till i=ack_seqlen will be sequence number
}
seq_no = atoi(ack_seq_char);
printf("Ack received for the sequence number %d\n",seq_no);
j =0;
for(i=1+ack_seqlen;i<2+ack_seqlen;i++) //next byte will have the length of checksum
{
temp_buf[j] = ack_buf[i]; //extracting the checksum length
j++;
}
temp_buf[j] = '\0'; //ending the string with a null character
strcpy(ack_check_len,temp_buf); //length of checksum will be in string format
ack_checksum_len = atoi(ack_check_len); //convert it into int
j = 0;
for(i=2+ack_seqlen;i<(2+ack_seqlen+ack_checksum_len);i++) //extract the checksum
{
ack_check[j] = ack_buf[i];
j++;
}
ack_check[j] ='\0';
ack_checksum = atoi(ack_check); //the checksum will be in string format,convert it into the integer format
j=0; //extract the content i.e the actual ack message
while(i<n)
{
content[j] = ack_buf[i];
i++;
j++;
}
content[j] ='\0';
length1 = strlen(content);
actual_checksum = checksum(content,length1);//calculate the actual checksum
printf("checksum of the ack received is %d\t and the checksum of the ack sent is %d\n",actual_checksum,ack_checksum);
if(actual_checksum == ack_checksum) //if the ack is not corrupt then update the base
{
printf("successfully recived packet %d\n",seq_no);
base =seq_no+1;
if(base == nextseqnum) //go to sending next series of packets
{
printf ("base is %d\n", base);
break;
}
else
{
initial = clock(); //start timer for next in-flight packet
}
}
else //if it is a corrupt ack
{
printf("Ack corrupted,wait till timeout\n");
}
} else {
if (end_flag == 1) {
printf ("Reached END\n");
break;
}
}
}
else //if the timer is out, resend the packet from the packet with seqno
// base till nextseqnum-1,start timer
{
initial = clock();
sequence = base;
while(sequence <= nextseqnum-1)
{
n= sendto(sock,data[sequence],total_len[sequence],0,(struct sockaddr *)&server,sizeof(struct sockaddr));///send the data packet after adding the header info
if(n<0)
{
printf("error in sending message to the server");
fclose(fp);
return 1;
}
sleep(0.5);
}
}
}
if(end_flag == 1) //if there had been an error in reading file of EOF had reached break out of
// the outermost while loop
{
printf ("I am at the END\n");
break;
}
}
printf ("Sending finish packet\n");
strcpy(buff,"Finish");
n= sendto(sock,buff,1024,0,(struct sockaddr *)&server,sizeof(struct sockaddr));
if(n<0)
{
printf("error in sending message to the server");
return 1;
}
fclose(fp); //close the file to complete the transmission
t = clock()-t;
gettimeofday(&end,NULL);
double time_taken = ((double)t)/CLOCKS_PER_SEC; //in secconds
printf(" The CPU time for transmission %f seconds \n",time_taken);
double delta = ((end.tv_sec - start.tv_sec)*1000000u+ end.tv_usec - start.tv_usec)/1.e6;
printf("The actual execution time took %f seconds\n", delta);
close(sock); //close api tries to complete the transmission if there is data waiting to be transmitted
return 0;
}

select socket call send and recv synchronization

I am using the select call and accepting the connection from "X" no of clients.
I made duplex connection i.e. server to client and client to server.
When connection is established between 2 entities ,I am going to send
data in chunks from one entity to other.
During send I read one file in chunks and send the data in chunks.
while(file_size !=0)
{
read_bytes = read(fd, buff, sizeof(buff));
cnt_ = send(_sock_fd,buff,actually_read,0);
file_size = file_size - cnt_;
printf("total sent remaining %d : %d\n",size,actually_read);
}
while at receiver side
//First I send the header which contain size it got accepted fine but during the following send call I used "get_readable_bytes" (Using ioctl) which returns me the no of bytes arrived at socket
`while(size != 0)
{
int test_ = 0;
while(((cnt_= get_readable_bytes(_sock_fd))== 0) )//&& test_ == 0
{
cnt_= get_n_readable_bytes(_sock_fd);
printf("Total bytes recved %d\n",cnt_);
//test_ = test_ + 1;
}
while(cnt_ != 0)
{
actually_read = recv(_sock_fd, buff, sizeof(buff),0);
int _cnt = get_n_readable_bytes(_sock_fd);
printf("Total bytes recved %d\n",cnt_-_cnt);
write(_fd,buff,actually_read);
cnt_ = cnt_ - actually_read;
test_ = 0;
}
`Now the problem is
1.During this execution of receive function control automatically go to the select function and it tries to execute whole receive function again so is there any way to synchronize the sender and receivers such that when the sender complete then start receiver or as soon as sender start receiver ?
2.And how do I maintain the count of bytes sent and received.
and this is my select call
`is_read_availble = select(maxfd + 1,&read_set,NULL,NULL,&timeout)`
with timeout 10sec.
Sketch of the kind of buffer code you need. (To allow partial reads/writes, the buffers need to be persistent between calls) BTW: you really need to handle the -1 return from read() and write() because they would seriously disturb your buffer-bookkeeping. EINTR + EAGAIN/EWOULDBLOCK is very common.
struct buff {
unsigned size;
unsigned bot;
unsigned top;
char *buff;
};
struct buff bf = {0,0,0,NULL};
initialisation:
bf.buff = malloc(SOME_SIZE);
/* ... error checking omitted */
bp.size = SOME_SIZE;
bp.bot = bp.top =0;
reading:
unsigned todo;
int rc;
/* (maybe) shift the buffer down to make place */
todo = bf.top - bf.bot;
if (todo) {
memmove (bf.buff, bf.buff + bf.bot, todo);
bf.top = todo; bf.bot = 0;
}
todo = bf.size - bf.top;
if (!todo) { /* maybe throttle? ... */ return; }
rc = read (fd, bf.buff+bp.top, todo);
/* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc == 0) {...}
else {
total_read += rc;
bp.top += rc;
}
writing:
unsigned todo;
int rc;
todo = bf.top - bf.bot;
if (!todo) { /* maybe juggle fd_set ... */ return; }
rc = write (fd, bf.buff+bp.bot, todo);
/* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc ==0) { ...}
else {
bp.bot += rc;
total_written += rc;
if (bp.bot == bp.top) bp.bot = bp.top =0;
}
/* ... this is the place to juggle the fd_set for writing */

C++ code to find BSSID OF associated network

Hello I've written the following code which is a part of a project. It is used to find the ESSID of the current associated network.
But it has a flaw: it also the displays the ESSID of the network with which I am not associated i.e. if I try to associate myself with a wireless n/w and if it is unsuccessful i.e. NO DHCP OFFERS ARE RECEIVED, then also it will display the that ESSID with which I have made my attempt.
Could anyone give me an ioctl call to find the BSSID of current associated wireless n/w?. In my opinion it is the only way with which I a can mark b/w associated and non associated.
CODE:-
int main (void)
{
int errno;
struct iwreq wreq;
CStdString result = "None";
int sockfd;
char * id;
char ESSID[100];
memset(&wreq, 0, sizeof(struct iwreq));
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Cannot open socket \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description is : %s\n",strerror(errno));
return result ;
}
CLog::Log(LOGINFO,"Socket opened successfully");
FILE* fp = fopen("/proc/net/dev", "r");
if (!fp)
{
// TBD: Error
return result;
}
char* line = NULL;
size_t linel = 0;
int n;
char* p;
int linenum = 0;
while (getdelim(&line, &linel, '\n', fp) > 0)
{
// skip first two lines
if (linenum++ < 2)
continue;
p = line;
while (isspace(*p))
++p;
n = strcspn(p, ": \t");
p[n] = 0;
strcpy(wreq.ifr_name, p);
id = new char[IW_ESSID_MAX_SIZE+100];
wreq.u.essid.pointer = id;
wreq.u.essid.length = 100;
if ( ioctl(sockfd,SIOCGIWESSID, &wreq) == -1 ) {
continue;
}
else
{
strcpy(ESSID,id);
return ESSID;
}
free(id);
}
free(line);
fclose(fp);
return result;
}