C++/TCP data transfer garbage - c++

I'm a beginner C++/TCP programmer and I was doing a home assignment for file transfer using TCP in C++/VS2010/Windows 7.
I've created a client and a server that can listen to multiple clients on a network.
When I send a request to the server requesting a file, I receive the correct size of file, but when I send data from server to client I get garbage.
I'm pretty sure I've done a stupid mistake somewhere with casting, but can't identify where.
I am sending char* byte by byte and save them to a file on the client.
Any ideas what's wrong?
// client code:
unsigned int packlen = 0;
unsigned int flength = 0;
char* data = NULL;
if((packlen = recv(sock, (char*) &flength, sizeof(unsigned int), 0)) ==
sizeof(unsigned int))
{
flength = (unsigned int) flength;
data = new char[flength];
}
unsigned char current;
char* buffer;
unsigned int accumlength = 0;
for(unsigned int i = 0; i < flength; ++i)
{
if((packlen = recv(sock, (char*) &current , sizeof(unsigned int), 0))
!= sizeof(unsigned int))
{
err_sys("Receiving packet transfer error., exit");
}
data[i] = current;
}
ofstream output(argv[2], ios::binary);
output.write(data, flength);
if(data)
{
delete[] data;
data = NULL;
}
// Server code:
char* data = NULL;
unsigned long length;
string fname;
data = new char[stat_buf.st_size];
ifstream input(reqp->filename, ios::binary);
input.seekg(0, ios::end);
unsigned int length = input.tellg();
if(length != stat_buf.st_size)
{
err_sys("Problems with file size");
}
send(cs, (char*) &length, sizeof(unsigned int), 0);
Sleep(1000); // wait a bit
input.read(data, length); // read all file at once.
for(unsigned int i = 0; i < length; ++i)
{
unsigned char current = data[i];
send(cs, (char*) &current, sizeof(unsigned char), 0);
}
Thanks for your help.

It looks like you are discarding quite a few bytes during the read loop:
recv(sock, (char*) &current, sizeof(unsigned int), 0)
Where current is an unsigned char but you ask it to read sizeof(unsigned int) bytes which are more than that. So recv() will write its result somewhere else (because it will write 4 bytes in current)
You should probably write:
recv(sock, (char*) &current, 1, 0)
Even though that is terribly inefficient it should at least work.

Related

C++ websocket server handling message fragmentation

I am trying to send images through websocket from one javascript/html client to another. The problem is that the server is incorrectly receiving the image. I am sending all the images as data URI's in text so that when the javascript client receives it, it can just simply set the src of the img to the URI. The problem (I believe) comes from how I am handling message fragmentation. Sending simple text messages work fine so I led to believe its the size of the message that's causing issues, and the only main code difference is how I handle message fragmentation. From this documentation, I am led to believe that all that must be done is to unmask the payload of each fragmented frame and concatenate the buffers together. The URI read on the server is sufficiently shorter than the actual data URI of the image. On the client end all I am doing is calling the socket.send() function. I have confirmed that the data URI I read in the javascript FileReader is correct (on the client side).
int wSock::readData(/*input socket data buffer*/ char ** sockp, /*output payload*/ char ** buffer, /*output payload info*/ WebSocketFrameData * data) {
char * sock = *sockp;
if (!webSocketIsOpened(sock)) return -32; //checks if the socket is open
u_long package_size;
SOCKET socket;
size_t dataRead = 0;
size_t dr = 0;
size_t firstLength = 0;
memcpy_s(&socket, 4, sock, 4);
ioctlsocket(socket, FIONREAD, &package_size);
if (package_size <= 0) return 1;
char * buf = new char[package_size + 1];
while (dataRead < package_size) {
dr = recv(socket, buf + dataRead, package_size - dataRead, NULL);
if (dr == SOCKET_ERROR) {
delete[] buf;
return WSAGetLastError();
}
dataRead += dr;
}
*(buf + package_size) = '\0';
if (package_size > 0) {
decodeFrame(buf, buffer, &firstLength);
if (data != NULL) {
data->payloadLength = firstLength;
data->opcode = *buf & 0b00001111;
}
}
else return 1;
// code handling other opcodes such as a close frame or a ping
char fin = (*buf) >> 7;
if (!fin) { //start handling message fragmentation
printf("Fragmentation! \n");
FD_SET tempRead;
size_t totalLength = firstLength -1; //firstLength includes the null terminator
char * combinedPayloads = new char[totalLength];
memcpy_s(combinedPayloads, totalLength, *buffer, totalLength);
printf("First frage of size: %u \n", totalLength);
while (fin != 1) {
FD_ZERO(&tempRead);
FD_SET(socket, &tempRead);
select(0, &tempRead, NULL, NULL, NULL);
package_size = 0;
ioctlsocket(socket, FIONREAD, &package_size);
printf("Reading next frag of size: %u \n", package_size);
char * contBuf = new char[package_size];
dataRead = 0;
while (dataRead < package_size) {
dr = recv(socket, contBuf + dataRead, package_size - dataRead, NULL);
if (dr == SOCKET_ERROR) {
delete[] contBuf;
return WSAGetLastError();
}
dataRead += dr;
}
char * payload;
size_t payloadLength = 0;
decodeFrame(contBuf, &payload, &payloadLength);
payloadLength--; //the output payloadLength from the decodeFrame function includes a null terminator
char * backBuffer = new char[totalLength];
memcpy_s(backBuffer, totalLength, combinedPayloads, totalLength);
delete[] combinedPayloads;
combinedPayloads = new char[totalLength + payloadLength];
memcpy_s(combinedPayloads, totalLength, backBuffer, totalLength);
memcpy_s(combinedPayloads + totalLength, payloadLength, payload, payloadLength);
fin = contBuf[0] >> 7;
totalLength += payloadLength;
delete[] backBuffer;
delete[] contBuf;
delete[] payload;
if (fin) break;
}
delete[] *buffer;
*buffer = new char[totalLength + 1];
memcpy_s(*buffer, totalLength, combinedPayloads, totalLength);
(*buffer)[totalLength] = '\0';
delete[] combinedPayloads;
data->payloadLength = totalLength;
printf("Finished fragment! Total size: %u \n", totalLength);
}
delete[] buf;
return 0;
}
And this is the code for decoding each websocket frame. As I mentioned the server works fine for smaller chat messages so I assume the problem is the message re-assembling but I will include the decodeFrame function with hopes that it well help understanding.
int wSock::decodeFrame(char * message, char ** output, size_t * payloadLength)
{
char read;
memcpy_s(&read, 1, message + 1, 1);
unsigned long long size = read & 0b01111111;
//takes bits 9 - 15;
int lastByte = 2;
if (size == 126) {
unsigned short rr;
memcpy_s(&rr, 2, message + 2, 2);
size = ntohs(rr);
lastByte = 4;
}
else if (size == 127) {
unsigned long long data;
memcpy_s(&data, 8, message + 2, 8);
size = ntohll(data);
lastByte = 10;
}
if(payloadLength != NULL)
*payloadLength = size + 1;
char mask[4];
memcpy_s(mask, 4, message + lastByte, 4);
*output = new char[(size + 1)];
lastByte += 4;
for (int i = 0; i < size; i++) {
(*output)[i] = message[lastByte + i] ^ mask.mask[i % 4];
}
(*output)[size] = '\0';
return 0;
}
On the server side for debugging, I took the read message and wrote it into a text file. However, the URI that was written is only about 4,000 - 6,000 characters long and the last 200 - 400 characters are not valid base64 characters, however the characters before these invalid characters do match their corresponding characters on the real data URI. The printf statement during the re-assembling process will tend to read about 262,368 bytes (total) while the actual URI is 389,906 characters long. After reading the URI the server sends it to the clients, which causes them to disconnect. So as I mentioned my guess is that something is going wrong when I'm re-assembling the data frames. Any help will be appreciated.
ioctlsocket(socket, FIONREAD, &package_size);
FIONREAD returns the number of bytes that can be read without blocking. This means that the recv() loop following this line of code is completely futile One recv() will read that amount of data. It can't not.
You are also not handling end of stream correctly (recv() returns zero).
OK, I figured it out. What I forgot to account for was TCP message fragmentation. As #EJP mentioned, ioctlsocket returns only the amount of bytes that can be read in one single recv() call. I was treating each fragment of data received as its own WebSocket frame while that wasn't always the case. Often times (almost all the time) the single recv() call would only read a partial frame, and the next part of the first frame would be read with the first part of the second frame at the second recv() call. Then the second buffer (which is now a mix of two different incomplete frames) would obviously not be demasked properly and the decoded size would be incorrect. The javascript client was fragmenting each WebSocket frame at around 131K bytes and the underlying TCP layer would fragment those frames further into around 65K byte packets. So what I did is I received all the data I could in a single recv() call, and then use a function along the lines of:
unsigned long long wSock::decodeTotalFrameSize(char * frame)
{
char secondByte = 0;
memcpy_s(&secondByte, 1, frame + 1, 1);
unsigned long long size = secondByte & 0b01111111;
int headerSize = 2 + 4;
if (size == 126) {
unsigned short length;
memcpy_s(&length, 2, frame + 2, 2);
size = ntohs(length);
headerSize += 2;
}
else if (size == 127) {
unsigned long long length;
memcpy_s(&length, 8, frame + 2, 8);
size = ntohll(length);
headerSize += 8;
}
return size + headerSize;
}
to get the total WebSocket frame size. Then loop until you read that amount of bytes into a single frame. Something similar to:
FD_ZERO(&tempRead);
FD_SET(socket, &tempRead);
select(0, &tempRead, NULL, NULL, NULL);
package_size = 0;
ioctlsocket(socket, FIONREAD, &package_size);
char * contBuf = new char[package_size];
dataRead = 0;
dr = recv(socket, contBuf, package_size, NULL);
if (dr == SOCKET_ERROR) {
delete[] contBuf;
return WSAGetLastError();
}
unsigned long long actualSize = decodeTotalFrameSize(contBuf);
if (package_size < actualSize) {
char * backBuffer = new char[package_size];
memcpy_s(backBuffer, package_size, contBuf, package_size);
delete[] contBuf;
contBuf = new char[actualSize];
memcpy_s(contBuf, actualSize, backBuffer, package_size);
delete[] backBuffer;
dataRead = package_size;
dr = 0;
while (dataRead < actualSize) {
dr = recv(socket, contBuf + dataRead, actualSize - dataRead, NULL);
if (dr == SOCKET_ERROR) {
delete[] contBuf;
return WSAGetLastError();
}
else if (dr == 0) break;
dataRead += dr;
}
printf("Read total frag of %u \n", dataRead);
}

C/C++ How to read file to char array for encrypting

I have a simple implementation of AES (CTR Mode, which allows encrypting/decrypting more than 16bytes)
And I want to read a file to a char array and then to encrypt it.
I have tried the following, without success:
long GetFileSize(const char* filePath)
{
FILE* pFile = fopen(filePath, "rb");
if (pFile == NULL)
{
printf("error");
getchar();
}
fseek(pFile, 0, SEEK_END);
long lSize = ftell(pFile);
rewind(pFile);
fclose(pFile);
return lSize;
}
// Reads given file to buffer, and returns pointer to that buffer.
// Caller should free this memory later.
unsigned char * ReadFile(const char * filePath)
{
FILE * pFile;
long lSize;
unsigned char * buffer;
size_t result;
pFile = fopen(filePath, "rb");
if (pFile == NULL) { fputs("File error", stderr); ; }
// obtain file size:
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
// allocate memory to contain the whole file:
buffer = (unsigned char*)malloc(sizeof(unsigned char)*lSize);
if (buffer == NULL) { fputs("Memory error", stderr); ; }
// copy the file into the buffer:
result = fread(buffer, 1, lSize, pFile);
if (result != lSize) { fputs("Reading error", stderr); ; }
// terminate
fclose(pFile);
// the whole file is now loaded in the memory buffer. Return pointer to data.
return buffer;
}
int main(int argc, char *argv[])
{
//All char arrays are null terminated here...
uchar szkey[KEY_128] = "very strong key";
const char *filePath = "key.txt";
// Get file size which must be encrypted
long originalSize = GetFileSize(filePath);
// Make this size multiple of block size (16 bytes).
long multipleSize = (originalSize / 16 + 1) * 16;
// Store number of bytes that were needed for padding.
int nrOfPaddingBytes = (int)(multipleSize - originalSize);
// Now, read the file.
unsigned char * fileContents = ReadFile(filePath);
// Create a large buffer to store file contents (including padding bytes),
// and copy file contents to it.
unsigned char * buffer = (unsigned char*)malloc(multipleSize);
memcpy(buffer, fileContents, originalSize);
// Allocate space for ciphertext also (should also have size multiple of 8).
unsigned char * ciphertext = (unsigned char*)malloc(multipleSize);
char* cipherhex = (char*)malloc(multipleSize * 2);
char* decryptedhex = (char*)malloc(multipleSize);
unsigned char* dechex = (unsigned char*)malloc(multipleSize);
// Delete old file buffer.
free(fileContents);
fileContents = NULL;
// Pad the plaintext
for (int i = 0; i < nrOfPaddingBytes; i++)
{
buffer[originalSize + i] = nrOfPaddingBytes;
}
aes_ctx_t *ctx;
u64 nonce;
virtualAES::initialize();
ctx = virtualAES::allocatectx(szkey, sizeof(szkey));
virtualAES::rand_nonce(&nonce);
//encrypt
virtualAES::encrypt_ctr(ctx, buffer, ciphertext, sizeof(buffer), nonce);
cout << "cipherdata in ansi:\n" << ciphertext << "\n\n";
virtualAES::strtohex(ciphertext, cipherhex, originalSize);
cout << "cipherdata in hex:\n" << cipherhex << "\n\n";
return 0;
}
but it fails for some reason. Could someone provide me an algorithm to read a file for encrypting?

c++ socket recv function loop

Im trying to send and receive 2 data back to back on tcp socket. Protocol is written below.
Client send data
On receiving the data on sever it sends back to client
Now using below client code I'm not able to get 2nd data and I think the 'Recv' function doing something wrong. Below is the code snippet.
int Recv(char* buffer, int size)
{
int total = 0, n = 0;
while((n = ::recv(m_hSocket, buffer+total, size-total-1, 0)) > 0)
{
total += n;
}
buffer[total] = 0;
return total;
}
int SendAndReceiveData()
{
//CStringA cstData :: this data getting filled by some other code. Ignore!
//Send data
char chSendBuff[256];
memset(chSendBuff, 0, sizeof(chSendBuff));
sprintf_s(chSendBuff, sizeof(chSendBuff), "%s", (LPCTSTR)cstData);
send(m_hSocket, chSendBuff, (int)strlen(chSendBuff), 0);
//Read response
char chRecvBuff[256];
memset(chRecvBuff, 0, sizeof(chRecvBuff));
int iRet = Recv(chRecvBuff, 256);
}
Your receive function should look like this:
int receive(int sockfd, void *buf, size_t len, int flags)
{
size_t toread = len;
char *bufptr = (char*) buf;
while (toread > 0)
{
ssize_t rsz = recv(sockfd, bufptr, toread, flags);
if (rsz <= 0)
return rsz; /* Error or other end closed connection */
toread -= rsz; /* Read less next time */
bufptr += rsz; /* Next buffer position to read into */
}
return len;
}

Send binary file over TCP/IP connection

I will rephrase the whole question here so that it is answerable.
I am able to copy binary file perfectly in the same machine not using sockets but just making a simple copy function. Trying to implement this code for copying onto a TCP/IP connection but can't get it to work.
FILE *filehandle = fopen("imagefile.jpg", "rb");
FILE *dest =fopen("imagecopy.jpg", "wb"); // copied image file
fseek(filehandle, 0, SEEK_END);
unsigned long filesize = ftell(filehandle);
char *buffer = (char*)malloc(sizeof(char)*filesize);
rewind(filehandle);
int bytesread = fread(buffer, sizeof(char), filesize, filehandle);
for( int i=0; i<filesize; i++ )
{
fputc(buffer[i], filehandle); // copies all the contents to dest
}
The code above works perfectly for copying an image file in the computer but when implemented to copy on server, it is difficult to go about it.
I am trying to send an image file from a server to a client both which have been made manually in C. The length of the file to be sent by the server is only known to the server when it's sending the file so the buffer is dynamically generated in the server, something like this:
SERVER
fseek(filehandle, 0, SEEK_END);
long filesize = ftell(filehandle); // file could be 11000bytes
char *buffer = (char*)malloc(sizeof(char)*filesize); // char buffer with 11000 bytes to store the data from the file.
// then I call the send() function
rewind(filehandle); // go back to beginning
send(clientsocket, buffer, filesize, 0); // this is being sent perfectly, no errors because in the actual code, I am checking for errors
CLIENT
// here is where I don't understand how to dynamically allocate the 11000 bytes to store the data in a client buffer
// the filesize is not necessarily going to be 11000 so need to dynamically allocate
// I did the following:
#define BUFSIZE 10
FILE *filehandle = fopen("imagefile.jpg", "wb"); // image file created by client
char *buffer = (char*)malloc(sizeof(char)*BUFSIZE);
int bytesread = recv(buffer, 1, strlen(buffer), 0);
if( bytesread > 0 )
{
printf("Bytes read: %d\n", bytesread); // bytes read is 5
printf("Buffer: %s\n", buffer); // but buffer shows all the binary text like it normally would
// when I try to store buffer in a file, it doesn't put full buffer because only 5 characters are written
for( int i=0; i<bytesread; i++ )
{
fputc(buffer[i], filehandle); // this doesn't create full image
}
}
How can I dynamically allocate the 11000 bytes sent by the server?
You need to loop both the sending and receiving. Neither send() nor recv() are guaranteed to send/read as many bytes as you requested.
You also should send the file size before the file data so the receiver knows how many bytes to expect and when to stop reading.
Try something more like this:
SERVER
bool senddata(SOCKET sock, void *buf, int buflen)
{
unsigned char *pbuf = (unsigned char *) buf;
while (buflen > 0)
{
int num = send(sock, pbuf, buflen, 0);
if (num == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
// optional: use select() to check for timeout to fail the send
continue;
}
return false;
}
pbuf += num;
buflen -= num;
}
return true;
}
bool sendlong(SOCKET sock, long value)
{
value = htonl(value);
return senddata(sock, &value, sizeof(value));
}
bool sendfile(SOCKET sock, FILE *f)
{
fseek(f, 0, SEEK_END);
long filesize = ftell(f);
rewind(f);
if (filesize == EOF)
return false;
if (!sendlong(sock, filesize))
return false;
if (filesize > 0)
{
char buffer[1024];
do
{
size_t num = min(filesize, sizeof(buffer));
num = fread(buffer, 1, num, f);
if (num < 1)
return false;
if (!senddata(sock, buffer, num, 0))
return false;
filesize -= num;
}
while (filesize > 0);
}
return true;
}
FILE *filehandle = fopen("imagefile.jpg", "rb");
if (filehandle != NULL)
{
sendfile(clientsocket, filehandle);
fclose(filehandle);
}
CLIENT
bool readdata(SOCKET sock, void *buf, int buflen)
{
unsigned char *pbuf = (unsigned char *) buf;
while (buflen > 0)
{
int num = recv(sock, pbuf, buflen, 0);
if (num == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
{
// optional: use select() to check for timeout to fail the read
continue;
}
return false;
}
else if (num == 0)
return false;
pbuf += num;
buflen -= num;
}
return true;
}
bool readlong(SOCKET sock, long *value)
{
if (!readdata(sock, value, sizeof(value)))
return false;
*value = ntohl(*value);
return true;
}
bool readfile(SOCKET sock, FILE *f)
{
long filesize;
if (!readlong(sock, &filesize))
return false;
if (filesize > 0)
{
char buffer[1024];
do
{
int num = min(filesize, sizeof(buffer));
if (!readdata(sock, buffer, num))
return false;
int offset = 0;
do
{
size_t written = fwrite(&buffer[offset], 1, num-offset, f);
if (written < 1)
return false;
offset += written;
}
while (offset < num);
filesize -= num;
}
while (filesize > 0);
}
return true;
}
FILE *filehandle = fopen("imagefile.jpg", "wb");
if (filehandle != NULL)
{
bool ok = readfile(clientsocket, filehandle);
fclose(filehandle);
if (ok)
{
// use file as needed...
}
else
remove("imagefile.jpg");
}
We could avoid the header that contains the image size, but we just read to the end of the sent data. About the buffer size, we could use a fixed number such as 10 * 1024, when we received some data from the server, we just save it into a file according to the actual received data length.
// please open a file ...
FILE * fp;
// ...
const int LENGTH = 10 * 1024;
int len = 0;
char * buffer = (char *)malloc(LENGTH);
while ((len = recv(socket, buffer, LENGTH, 0)) > 0) {
fwrite(buffer, 1, len, fp);
}
free(buffer);
// close the file
#T.C: I guess we cannot allocate a buffer according to the size sent from the server in case the image is too large to save inside the client's memory. Not mention the server is fake, and intended to make any attack.

Cannot transfer images received from FTP client onto my FTP server

Using the below code, I'm able to read and store text files sent by FTP clients to my FTP server just fine, but images and other binary data ends up being corrupted. I'm sure I'm overlooking something in the spec. Is the error obvious?
//open the file sepcified for output
std::ofstream stor_file(cmd_arg, std::ios::binary);
unsigned buf_size = 500;
unsigned char *buf = new unsigned char[ buf_size ];
const char *open_conn = "150 openeing data connection\r\n";
CNetwork::write_to_socket( cntl_fd, open_conn, strlen(open_conn) );
// slurp the whole file from the socket
int bytes_read = read( data_fd, buf, buf_size);
while (bytes_read > 0)
{
// write what's in the buffer to the file
for (int i = 0; i < bytes_read; ++i)
{
stor_file << buf[i];
}
memset( buf, 0, sizeof( buf ) );
bytes_read = read( data_fd, buf, sizeof( buf ));
}
delete [] buf;
// done writing...close the file!
stor_file.close();
// write to socket: "226 File successfully transferred\r\n";