there's something strange in my client/server socket using RSA.
If i test it on localhost, everithing goes fine, but if i put client on a pc and server on othe pc, something gone wrong.
Client after call connect, call a method for public keys exchange with server. This part of code works fine.
After this, client send a request to server:
strcpy(send_pack->op, "help\n");
RSA_public_encrypt(strlen(send_pack->op), send_pack->op,
encrypted_send->op, rsa_server, padding);
rw_value = write(server, encrypted_send, sizeof (encrypted_pack));
if (rw_value == -1) {
stampa_errore(write_error);
close(server);
exit(1);
}
if (rw_value == 0) {
stampa_errore(no_response);
close(server);
exit(1);
}
printf("---Help send, waiting for response\n");
set_alarm();
rw_value = read(server, encrypted_receive, sizeof (encrypted_pack));
alarm(0);
if (rw_value == -1) {
stampa_errore(read_error);
exit(1);
}
if (rw_value == 0) {
stampa_errore(no_response);
close(server);
exit(1);
}
RSA_private_decrypt(RSA_size(rsa), encrypted_receive->message,
receive_pack->message, rsa, padding);
printf("%s\n", receive_pack->message);
return;
}
but when server try to decrypt the receive message on server side, the "help" string doesn't appear. This happen only on the net, on localhost the same code works fine...
EDIT:
typedef struct pack1 {
unsigned char user[encrypted_size];
unsigned char password[encrypted_size];
unsigned char op[encrypted_size];
unsigned char obj[encrypted_size];
unsigned char message[encrypted_size];
int id;
}encrypted_pack;
encrypted_size is 512, and padding used is RSA_PKCS1_PADDING
You are assuming that you read the whole thing, 512 sizeof (encrypted_pack) bytes, in one go. This doesn't always happen. You can get less than that, so you should read(2) in a loop until you have your complete application message.
Edit 0:
You are trying to decrypt not complete message. TCP is a stream of bytes, and you have to treat it as such. It doesn't know about your application message boundaries. You should be doing something like this:
char buffer[sizeof( encrypted_pack )];
size_t to_read = sizeof( encrypted_pack );
size_t offset = 0;
while ( true ) {
ssize_t rb = ::read( fd, buffer + offset, to_read - offset );
if ( rb == -1 ) { /* handle error */ }
else if ( rb == 0 ) { /* handle EOF */ }
else {
offset += rb;
to_read -= rb;
if ( to_read == 0 ) break;
}
}
// handle complete message in buffer
You should do the same - write bytes into the socket in a loop - on the sending side too.
It "works" over loopback because MTU of that virtual interface is usually around 16K vs. 1500 for normal ethernet, so TCP transfers your data in one chunk. But you cannot rely on that.
Related
I am trying to write and read Integer value into/from C socket. Sometimes ntohs() return very big values like 55000 , 32000 etc...Though client is always sending value <1500. If I run the program it happens after 10-15 minutes...Sometimes after 20-30 minutes.
Can you please check below code and tell me
Why this line getting printed ?
printf("Garbage value - ntohs problem ..Exiting... ");
// write exactly n byte
inline int write_n(int fd, char *buf, int n) {
int nwrite, left = n;
int totalwrite = 0;
while (totalwrite != n) {
if ((nwrite = write(fd, buf, left)) <= 0) {
break;
} else {
totalwrite = totalwrite + nwrite;
left -= nwrite;
buf += nwrite;
}
}
if (totalwrite == 0)
return nwrite;
return totalwrite;
}
// send exactly n byte
inline int send_n(int fd, char *buf, int n) {
int nwrite, left = n;
int totalwrite = 0;
while (totalwrite != n) {
if ((nwrite = send(fd, buf, left, MSG_NOSIGNAL)) <= 0) {
break;
} else {
totalwrite = totalwrite + nwrite;
left -= nwrite;
buf += nwrite;
}
}
if (totalwrite == 0)
return nwrite;
return totalwrite;
}
uint16_t nread, len, plength, nsend;
int MTU = 1500;
char buffer[2000];
// Server receive ( Linux 64 bit)
while (1) {
// read packet length
nread = read_n(TCP_SOCKFD, (char *) &plength, sizeof(plength));
if (nread <=0) {
break;
}
len = ntohs(plength);
if (len <=0 || len > 1500 ) {
**printf("Garbage value - ntohs problem ..Exiting... "); // WHY ?**
break;
}
// read packat data
nread = read_n(SOCKFD, buffer, len);
if (nread != len) {
break;
}
}
//---------------------
// CLIENT send ( Android 5 )
while (1) {
nread = read(tunfd, buffer, MTU);
if (nread <= 0 || nread > 1500) { // always <=1500
break;
}
plength = htons(nread);
// send packet lenght
nsend = send_n(TCP_SOCKFD, (char *) &plength, sizeof(plength));
if (nsend != sizeof(plength)) {
break;
}
// send packet data
nsend = send_n(TCP_SOCKFD, buffer, nread);
if (nsend != nread) {
break;
}
}
Thank you
We cannot tell you with certainty what's happening because you cannot provide a verifiable example. Additionally, you've not presented the implementation of read_n(), but supposing that it follows the same model as write_n() and send_n(), we can nevertheless perform some analysis.
Each of the data transfer functions returns a short count in the event that data transfer is interrupted by an error. The client code watches for this, and breaks out of its loop if it detects it. Well and good. The server code does not do this when reading plength, however. Since plength, as a uint16_t, is two bytes in size, a partial read is possible and would go unnoticed by your server code.
In your example, plength is modified only via the one read_n() call presented. Network byte order is big-endian, so the most-significant byte is read first. It is possible that the combination of that byte with the stale one left over from the previous read would represent a number exceeding 1500. For example, if a 221(0x00dd)-byte packet is followed by a 1280(0x0500)-byte packet, and a partial read occurs on the second packet size, then the combined result will be 1501(0x05dd).
I don't presently see any reason to think that the client sends data different in nature than you think it does, and I don't presently see any other way that your server code could give the appearance of receiving different data than the client sends, especially since client and server each abort at the first recognized sign of trouble.
Do note, however, that this code could still be made more robust. In particular, consider that read(), write(), and send() can fail even when there is no problem with the underlying socket or data transfer request. In particular, they can fail with EINTR if the call is interrupted by a signal, and if the socket is in non-blocking mode then they can fail with EAGAIN. There may be others. It does not seem useful to operate your socket in non-blocking mode, but you might indeed want to watch for EINTR and resume reading after receiving it.
I would also suggest that, at least during development, you emit more data about the nature of the error. Call perror(), for example, and afterward print the bad data. You might even consider logging data sent and received.
I want to connect/bridge two serial ports in C.
I have 2 threads reading the ports, and writing to the other port.
Here is one example:
void *rfid_to_uart_thread(void *) {
char rfid_read_buffer[100];
int writeCounter;
do {
writeCounter = read(rfidCom, rfid_read_buffer, sizeof(rfid_read_buffer)-1);
if (writeCounter > 0) {
write(uartCom, rfid_read_buffer, writeCounter);
} else
usleep(25);
} while (!bKillBridgeThreads);
return NULL;}
The problem is, it seems that the writes are too slow. I often receive only half of the String on the other side. It seems like the write is asynchronously and thus the buffer is overwritten again in the next loop and overwrites the last 'write', so that the data is crippled?!
Is that right?
The ports are opened NON_BLOCKING and RW, Baudrate is and has to be 9600.
Looking at the man:
read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf.
In other wordsread does not grants to return all bytes send by other task, can give you a single byte up to sizeof(rfid_read_buffer)-1
What you can do is:
loop reading from rfidCom until the number of chars matches the number of chars sent.
You can use a specific terminator of messages and check for it to validate received message
encapsulate chars into a protocol message with an header that embed the message length, so the receiver can count the received chars and stop reading when last char is received.
For example:
void *rfid_to_uart_thread(void *)
{
char rfid_read_buffer[100] = {0};
int writeCounter;
char RXchar;
ssize_t retVal;
bool send = false;
do
{
memset(rfid_read_buffer, 0x00, sizeof(rfid_read_buffer));
send = true;
do
{
retVal = read(rfidCom, &RXchar, 1);
if (retVal > 0)
{
rfid_read_buffer[writeCounter] = RXchar;
writeCounter++;
}
else if (retVal < 0)
{
send = false;
RXchar = '\r'
break;
}
else
{
usleep(25);
}
}
while(RXchar != '\r');
if (send)
{
write(uartCom, rfid_read_buffer, writeCounter);
}
}
while (!bKillBridgeThreads);
return NULL;
}
OK, I've found a solution to my problem I think.
void *rfid_to_uart_thread(void *) {
char rfid_read_buffer[10];
ssize_t writeCounter = -1;
do {
writeCounter = read(rfidCom, &rfid_read_buffer, sizeof(rfid_read_buffer)-1);
if (writeCounter>0){
rfid_read_buffer[writeCounter] = 0;
LOGE("RFID -> UART: %s", rfid_read_buffer);
write(uartCom, rfid_read_buffer, writeCounter);
}else{
usleep(25);
}
tcdrain(uartCom);
} while (!bKillBridgeThreads);
return NULL;}
I've created my own define for a tcdrain, because the Android NDK I am using is not offering it in termios.h
Now, all the values seem to get transmitted to the UART port.
tcdrain is now defined as:
#define tcdrain(fd) ioctl(fd, TCSBRK, 1)
I'm trying to implement a working HTTP Client-Server application just to make practice with network programming.
The 2 programs have to follow this basic algorithm:
CLIENT - send a GET request
SERVER - send "+OK\r\n"
SERVER - send file size in bytes
SERVER - send file
CLIENT - send ACK
I'm having a lot of troubles in the reading part, probably because i perform some dirty read on the stream.
These are the 2 reading function that i'm using:
/* Reads a line from stream socket s to buffer ptr
The line is stored in ptr including the final '\n'
At most maxlen chasracters are read*/
int readline (SOCKET s, char *ptr, size_t maxlen)
{
size_t n;
ssize_t nread;
char c;
for (n=1; n<maxlen; n++)
{
nread=recv(s, &c, 1, 0);
if (nread == 1)
{
*ptr++ = c;
if (c == '\n')
break;
}
else if (nread == 0) /* connection closed by party */
{
*ptr = 0;
return (n-1);
}
else /* error */
return (-1);
}
*ptr = 0;
return (n);
}
and:
int readNumber(SOCKET s, long *num, int maxRead)
{
size_t n;
ssize_t nread;
int totRead;
long number=0;
for (n=1; n<maxRead+1; n++)
{
nread=recv(s, &number, sizeof(number), 0);
if (nread == sizeof(number))
{
totRead+=nread;
*num = number;
}
else if (nread == 0) /* connection closed by party */
{
*num = 0;
return (n-1);
}
else /* error */
{
printf("nread = %d\n", nread);
return (-1);
}
}
return (totRead);
}
this is the snippet of the main where i receive the +OK message and then the file size:
memset(rbuf,0,sizeof(rbuf)); //rbuf is the buffer where is store the read
printf("waiting for response...\n");
result = readline(s, rbuf, sizeof(rbuf)); //reading function is above
printf("Byte read(okMsg) = %d\n", result);
if (result <= 0)
//ERROR MANAGEMENT
{
printf("Read error/Connection closed\n");
closesocket(s);
SockCleanup();
exit(1);
}
else
{
long fileLength=0;
unsigned char *fBuf;
//RECEIVE OK
if(!strcmp(rbuf,"+OK\r\n"))
{
puts("+OK\n");
//RECEIVE FILE LEN
int nw = readNumber(s, &fileLength, 1); //reading function is above
printf("Byte read(fDim) = %d\n", nw);
printf("File is %ld bytes long\n", fileLength);
if(nw >0)
{
// RECEIVE FILE
}
}
}
When i send the "+OK\r\n" string the server tells me that it sends 8 bytes, but when i read i find the '\0' char only after 6 bytes.
By the way it reads correctly the message, but when i try to read the file size (that is a long) it gives me back a wrong number.
My opinion is that the stream buffer is dirty, and that i'm reading 2 bytes that are not part of the file size, but i'm not understanding why this happens.
Please ask me more info if i'm not clear enough.
SOLVED:
Thank you all for your answers!!!
You put me in the right mindset to understand what was wrong.
Look like the problem was this declaration in the server:
char *okMsg = "+OK\r\n";
instead of
char okMsg[] = "+OK\r\n";
that lead me to an undefined behavior.
long number=0;
for (n=1; n<maxRead+1; n++)
{
nread=recv(s, &number, sizeof(number), 0);
You forgot to design and implement a protocol to carry the data between your server and your client. Because TCP provides a stream of bytes, your protocol should be defined as a stream of bytes.
How many bytes convey this number? Is "however many bytes a 'long' happens to occupy on my platform" a good answer? What's the semantic meaning of the first byte? Is "whatever the first byte of a 'long' happens to mean on my platform" a good answer?
A good answer would be, "The size shall be conveyed as a 4-byte unsigned integer in little-endian byte order". Then make absolutely sure your code sends and receives in that format.
I'm writing a small and simple server (in C language for Linux stations).
A client requests a file to my server, my server asks this file to another server which sends it to my server.
My server should NOT receive ALL the file before sending it to the client BUT must send the bytes of the file so as they arrive.
This is an exercise in school so I can not dissociate myself from this requirement.
I have implemented the function explained below. The problem is that the client receives a non-deterministic number of bytes and NEVER the entire file.
int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size){
size_t n;
ssize_t nread;
ssize_t nwritten;
char c;
for (n=1; n<file_size; n++)
{
nread=recv(socketa, &c, 1, 0);
if (nread == 1)
{
nwritten = send(socketb,&c,1,0);
}
else if (nread == 0)
{
*buffer = 0;
return (-1); /* Errore */
}
else
return (-1); /* Errore */
}
}
*buffer = 0;
return (n);
}
Someone could kindly tell me where I'm wrong?
Is it an stupid idea to change the values SO_SNDBUF and SO_RCVBUF on both the server and the client?
Assuming the file_size is the total number of bytes you want to send, then your for loop will only send file_size - 1 bytes. In other words, you are off by one. Start from 0 instead to fix this:
for (n=0; n<file_size; n++)
{ //..
You capture the return value of send(), but you do not check to see if it was successful or not.
You are treating a 0 return value from recv() the same as an error. Since you do not show what you do after returning -1 from your function, I don't know if this may be contributing to your problem or not.
Certain errors on send() and recv() are "soft", in that you are allowed to retry the operation for those particular errors. One such error is EINTR, but check the documentation on your system to see if there are others.
In order to optimize performance and simplify your code, you can use splice()+pipes. Sendfile enables you to "forward" data between file descriptors, without the copy to user space.
Are you sure you have copied the correct code? That part as it is would not compile, there is a } in the last else which don't match with a corresponding {.
Also, how you get to know the file size? if it's send thru the socket as an integer, bear in mind the possible byte order of the source and destination machines.
Anyway, you are reading one byte at a time, you should improve it this way:
EDIT: use buffer and not the extra buff[2048];
int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size){
ssize_t nread;
ssize_t nwritten;
ssize_t bLeft=file_size;
while (bLeft > 0)
{
nread=recv(socketa, buffer, bleft, 0);
if (nread > 0)
{
nwritten = send(socketb, buffer, nread, 0);
bLeft -= nread;
buffer+=nread;
}
else if (nread == 0)
{
// I think this could raise a memory exception, read below
*buffer = 0;
return (-1); /* Errore */
}
else
{
return (-1); /* Errore */
}
}
// If buffer is allocated with file_size bytes this one will raise a memory exception
// *buffer = 0;
return (file_size-bLeft);
}
I'm trying to receive a single packet at a time from the server, since packets are going too fast, and each is of undefined size, calling recv() with number of bytes to read will read the first packet and maybe a part of the second packet. Since each packet is NULL terminated, I thought reading byte by byte until a NULL byte is received.
int recvLen = 0;
char TB;
char recvBuffer[1024];
while (recv(Socket, &TB, 1, 0) > 0 && TB != 0 && recvLen < 1024)
{
recvBuffer[recvLen] = TB;
recvLen++;
}
I don't think this method is efficient at all. If the server sent 1024 bytes, recv() will be called 1024 times.
Is there any other method to recv() until a NULL char is received, or some better method than this one I'm using?
EDIT:
i added the packet size infront of the data sent from the server, but now, if a false packet or even sometimes for no reason, packets gets messed up and no correct data is received. here is my code
#define UPLOAD_LEN 2755
int PacketSize, recvLen;
char Size[4];
char recvBuffer[UPLOAD_LEN+1];
while(1)
{
if(recv(Socket,Size,4,0)>0)
{
Size[4] = '\0';
PacketSize = atoi(Size);
if (PacketSize > UPLOAD_LEN || PacketSize <= 0) continue;
recvLen = recv(Socket, recvBuffer, PacketSize, 0);
} else recvLen = -1;
if (recvLen > 0)
{
recvBuffer[recvLen] = '\0';
ProcessData(recvBuffer);
}
else
{
closesocket(Socket);
}
}
I have never understood why communications protocols never support the one use case programmers expect to be able to do: exchange arbitrarily sized blobs with sends and recv's aligned on boundaries.
So theres no real shortcut here. You need to keep a persistent buffer that holds any data left over from the previous call to recv. Keep adding data to the end as you receive it, and return up to the terminating zero each time you find one. You'll probably have at least a partial following packet, so move that to the start of the buffer to serve as your initial state on the next call.
Create a buffer and extract your protocol messages from that. If the buffer does not contain a complete message, then recv() until it does. Here's a simple C implementation to buffer a socket (lightly tested, compiles on MS VS2008):
#include <winsock2.h>
#include <string.h>
typedef struct buffsock {
SOCKET s;
char* buf;
size_t maxlen;
size_t curlen;
} buffsock_t;
void buffsock_init(buffsock_t* bs,SOCKET s,size_t maxlen)
{
bs->s = s;
bs->buf = malloc(maxlen);
bs->maxlen = maxlen;
bs->curlen = 0;
}
void buffsock_free(buffsock_t* bs)
{
free(bs->buf);
bs->buf = NULL;
bs->maxlen = 0;
bs->curlen = 0;
bs->s = INVALID_SOCKET;
}
/* Attempt to fill internal buffer.
* Returns 0 if socket closed.
* Returns number of additional bytes in buffer otherwise.
*/
int buffsock_fill(buffsock_t* bs)
{
int bytes;
bytes = recv(bs->s,bs->buf + bs->curlen,bs->maxlen - bs->curlen,0);
if(bytes == SOCKET_ERROR)
return -1;
bs->curlen += bytes;
return bytes;
}
/* Return up to <bytes> from buffered socket.
* If return value 0 socket was closed.
* If return value >0 and <bytes socket received partial message.
*/
int buffsock_bytes(buffsock_t* bs,size_t bytes,void* msg)
{
while(bs->curlen < bytes)
{
int result;
result = buffsock_fill(bs);
if(result == -1)
return -1; /* error on socket */
if(result == 0)
break;
}
if(bytes > bs->curlen)
bytes = bs->curlen;
memcpy(msg,bs->buf,bytes);
bs->curlen -= bytes;
memmove(bs->buf,bs->buf + bytes,bs->curlen);
return bytes;
}
/* Implmementation of a protocol with two big-endian bytes indicating
* msg size followed by <size> bytes of message.
* Returns -1 if error on socket.
* Returns -2 if partial message recv'd (shouldn't happen as long as
* internal buffer is bigger than max message size).
* Returns -3 if user buffer not big enough to hold message.
* Returns size of message otherwise.
*/
int get_protocol_message(buffsock_t* bs,void* msg,size_t maxlen)
{
int bytes;
u_short len;
bytes = buffsock_bytes(bs,sizeof(u_short),&len);
if(bytes == 0)
return 0; /* socket closed, no more messages */
if(bytes == -1)
return -1; /* error on socket */
if(bytes < sizeof(u_short))
return -2; /* partial message */
len = ntohs(len);
if(len > maxlen)
return -3; /* message exceeds user buffer */
bytes = buffsock_bytes(bs,len,msg);
if(bytes < len)
return -2; /* partial message */
return bytes;
}
Use it like this:
int len;
char msg[256];
buffsock_t bs;
/* open a socket */
buffsock_init(&bs,sock,1024);
len = get_protocol_message(&bs,msg,sizeof(msg));
The key is TCP/IP has no concept of message boundaries, so recv() can return 1 to number of bytes requested. The received buffer could contain multiple or even partial messages.
This code just appends received data into a buffer. The protocol requests bytes from the buffer, and the buffer is filled from the socket. as bytes are removed the remaining buffered data is shifted to the beginning of the buffer.
In this case, two bytes are requested, converted to a length, then the remaining bytes are requested. If a request can't be satisfied, more data is recv'd.
Hope this helps.
There are several ways that you could do this.
Option #1: Before sending out any information, send out an int at the front of your packet which contains the size of the packet. Read this int, and then allocate a buffer which is the length of the int that you just received. Then you can recv() the entire packet at one time.
Option #2: Read in 1024 bytes at a time. recv() will give you back the number of bytes read. You can then use strlen() to figure out if you have more than one packet in your buffer. It would probably make the most sense to make this recursive(assuming that you could have several packets in 1024 bytes); so that you split the packets based on NULL bytes.