Stuck in while when transfer file through socket using TCP - c

I write program and it works fine, but i want to rewrite it using sendfile() and now i got stuck in a loop.
Server side:
send name = ok
send md5 checksum = ok
send size = ok
send file = ko
Client side:
recv name = ok
recv md5 cecksum = ok
recv size = ok
create dir and create file = ok
write data to created file = ko
P.S In previous version of program i stuck some time to, but it depend how much i use printf why? for e.x i add one line with printf program stuck, delete it, works fine.
UPDT: rewrite code client/server
client
/* Received file name */
int rc_byte = 0;
rc_byte = recv(fd, rx_tx_file->out_name, sizeof(rx_tx_file->out_name),0);
if (rc_byte < 0){
perror("Failed to receive file name: ");
exit(-1);
} else
printf("Recv out name %s\n", rx_tx_file->out_name);
//printf("file name rc %s\n", rx_tx_file->out_name);
trimm_path_name(rx_tx_file);
/* Received md5sum */
rc_byte = recv(fd, rx_tx_file->md5sum, sizeof(rx_tx_file->md5sum), 0);
if (rc_byte < 0) {
perror("Failed to receive check sum: ");
exit(-1);
} else
printf("recv md5s %s\n", rx_tx_file->md5sum);
/* Received file size */
rc_byte = recv(fd, &size, sizeof(size), 0);
if(rc_byte < 0) {
perror("Recevid size of file: ");
exit(-1);
}
printf("%d recv size\n", size);
to_read = size;
if (stat(dir, &st) == -1){
mkdir(dir, 0777);
}
send_data: (add func to server)
void send_data(int client_fd, m_file *rx_tx_file, int option, int size) {
int send_byte = 0;
int total_send = 0;
if (option == SEND_NAME) {
while (total_send < strlen(rx_tx_file->in_name)) {
send_byte = send(client_fd, rx_tx_file->in_name, sizeof(rx_tx_file->in_name),0);
if(send_byte == -1) {
perror("Failed to send file name to client: ");
exit(SEND_TO_CLIENT_ERROR);
}
total_send += send_byte;
}
}
else if (option == SEND_MD5) {
total_send = 0;
send_byte = 0;
while (total_send < strlen(rx_tx_file->md5sum)) {
send_byte = send(client_fd, rx_tx_file->md5sum, sizeof(rx_tx_file->md5sum),0);
if(send_byte == -1){
perror("Failed to send file md5sum to client: ");
exit(-1);
}
total_send += send_byte;
}
}
else if (option == SEND_SIZE) {
send_byte = send(client_fd, &size, sizeof(size),0);
if (send_byte == -1) {
perror("Failed to send size: ");
}
}
}
server:
client_fd = accept(server_fd, (struct sockaddr*) &client_addr, &length)
/*send name of file*/
send_data(client_fd, rx_tx_file, SEND_NAME, 0);
/*send md5 sum*/
take_check_sum(rx_tx_file,rx_tx_file->file_in, 0);
send_data(client_fd, rx_tx_file, SEND_MD5, 0);
/*send size of file*/
size = stats.st_size;
send_data(client_fd, rx_tx_file, SEND_SIZE, size);
remain_data = stats.st_size;
printf("File [%s] ready to send\ncheck sum [%s]\n", rx_tx_file->in_name,rx_tx_file->md5sum);
while (((send_byte = sendfile(client_fd, file_fd, &offset, size)) > 0) && (remain_data > 0))
{
remain_data -= send_byte;
printf("remain %d", remain_data);
}
printf("Succesfully");
Since i work with one client and pass file which should send on server side through command line args, i dont need to wait in while (client_fd = accpet) i just work with one connection and close server. Now its work good. But one question is open, how i should rewrite client side to recv data in a loop. I don't know which size i should recv and because of that i cant write right condition to my while loop. THX all for helping.

TCP is a stream. It has no message boundaries. Your code won't work because of that.
First, you send the name of the file:
send(client_fd, rx_tx_file->in_name, strlen(rx_tx_file->in_name)+1,0)
then you immediately send the md5 sum and then the file size:
send(client_fd, rx_tx_file->md5sum, strlen(rx_tx_file->md5sum)+1, 0)
send(client_fd, &size, sizeof(int),0)
Since the first two strings don't have a fixed number of bytes, it's quite likely that when you try to read the file size or md5 sum from the server you also read the size of the file and maybe even some of the file data.
First, stop trying to put as much of your send and read code as you can into the conditional clause of your if and while statements.
What exactly does
if (send(client_fd, rx_tx_file->md5sum, strlen(rx_tx_file->md5sum)+1, 0) == -1) {
perror("Failed to send file md5sum to client: ");
exit(-1);
}
gain you over
ssize_t bytes_sent = send(client_fd, rx_tx_file->md5sum, strlen(rx_tx_file->md5sum)+1, 0);
if ( bytes_sent < 0 )
{
perror("Failed to send file md5sum to client: ");
exit(-1);
}
Putting all that code into the if clause gains you nothing on the send. And what if strlen(rx_tx_file->md5sum)+1 is 87 and the send() call returns 15? That's a possible return value that your code can't handle because it stuffs everything into the if clause.
ssize_t bytes_sent = send(client_fd, rx_tx_file->md5sum, strlen(rx_tx_file->md5sum)+1, 0);
if ( bytes_sent < 0 )
{
perror("Failed to send file md5sum to client: ");
exit(-1);
}
else if ( bytes_sent < strlen(rx_tx_file->md5sum)+1 )
{
// partial send...
}
That's actually better coded as a loop.
You didn't post your receive code, but if it's in the same style you not only don't gain anything, by putting everything into the if clause you again can't do any decent error detection or correction.
If your file name recv code is similar to
char filename[1024];
if (recv(fd, &filename, sizeof(filename), 0) < 0) {
perror("Failed to read file name: ");
exit(-1);
}
you can't tell what you just received. How many bytes did you just receive? You may have received the file name. You may have received only part of the file name. You may have received the file name, the md5 sum, and some of the file contents itself.
You don't know what you received, and with your code you can't tell. If you zero out the file name and md5 receive buffers and only recv up to one byte less than the size of the buffer, you at least avoid undefined behavior. But if you don't zero out the buffer, or if you read up the the last byte of the buffer, you can also wind up without a nul-terminated string for your filename or md5 sum. And when you then try to treat it as a nul-terminated string you get undefined behavior.
And if you did get extra bytes in the recv calls you make before trying to read the file data, that explains why your code gets stuck - it already read some of the file contents before getting to the loop, so the loop will never see all the content - some of it is gone.

You should avoid using strlen here in your server:
if(send(client_fd, rx_tx_file->in_name, strlen(rx_tx_file->in_name)+1,0) == -1)
Rather just send fixed length string of size sizeof(rx_tx_file->out_name) as you expect in your client
If the filename is smaller just pad it with spaces to make it of length sizeof(rx_tx_file->out_name)
You should also put each receive call in while loop, and add checks that it actually received expected number of bytes, at times recv will just return partial data, you need to post another recv to receive rest of the expected data

Related

Properly sending and receiving buffers in C

I'm writing some server/client program in C Windows. I don't know if I'm sending and receiving buffers the right way, on google I only see people error checking it but not checking if the send() function sent less bytes then expected. This is an example from my project:
Client:
// send buffer size
uint32_t num = htonl(sizeBuffer);
char* converted_num = (char*)&num;
res = send(ClientSocket, converted_num, sizeof(uint32_t), 0);
if (res == SOCKET_ERROR)
{
printf("error send\n");
}
// send buffer
while (totalSent < sizeBuffer)
{
sent = send(ClientSocket, totalBuffer, sizeBuffer, 0);
totalSent += sent;
printf("sent: %d\n", sent);
printf("totalSent: %d\n", totalSent);
}
Server:
// recv buffer size
char b[sizeof(uint32_t)];
r = recv(s, b, sizeof(uint32_t), 0);
if (r == SOCKET_ERROR)
{
printf("error recv\n");
}
uint32_t sizeBuffer = ntohl_ch(&b[0]);
// recv buffer
while (totalReceived < sizeBuffer)
{
received = recv(s, buffer, sizeBuffer, 0);
strcat(totalBuffer, buffer);
bzero(buffer, 18384);
totalReceived += received;
printf("received: %d\n", received);
printf("totalReceived: %d\n", totalReceived);
}
printf("%s", totalBuffer);
The reason I use strcat() is because when I use printf() inside the while() loop it gets printed weirdly, like the previous buffer gets printed and the new buffer gets printed on top. I don't know why it behaves like this.
Is this the right way to send and receive buffers? And do I also have to check whether the size (num) of the buffer is send correctly, like how I send the buffer itself? If yes, how can I do that?

Weird win sock bug on non blocking recv()

This is my receive file function for a non overlapped socket.
HANDLE recvfile = CreateFile(fileinfo[0], FILE_APPEND_DATA, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (recvfile == INVALID_HANDLE_VALUE) {
sockprintf(sockfd, "[Error Creating File] : %ld", GetLastError());
}
else {
memset(recvbuf, '\0', BUFFER); // Clear main buffer
int total = 0; // Total bytes received
// set_blocking_mode(sockfd, FALSE);
do{ // IF Total is equal to expected bytes. Break the loop, And stop receiving.
fsize = recv(sockfd, recvbuf, BUFFER, 0); // Receive file
if (fsize == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
connected = FALSE;
printf("[X] Connection interrupted while receiving file %s for %s size.", fileinfo[0], fileinfo[1]);
}
write = WriteFile(recvfile, recvbuf, fsize, &dwBytesWritten, NULL); // Write file data to file
total += fsize; // Add number of bytes received to total.
} while(total != expected);
// set_blocking_mode(sockfd, TRUE);
if (write == FALSE)
{
sockprintf(sockfd, "[Error Writing file %s of %s size] Error : %ld.", fileinfo[0], fileinfo[1], GetLastError());
}
else {
sockprintf(sockfd, "\n[ Received File : %s ]\n[ File Size : %s bytes ]\n[ Bytes written : %ld ]\n", fileinfo[0], fileinfo[1], dwBytesWritten);
}
CloseHandle(recvfile);
}
This is working excellent! File Transfer is almost instant and with no errors or corrupted buffers.
I'm on Visual studio 2019. The Problem is, When I compile and move the Executable to a test Virtual machine. The program crashes. Tested on Windows 10 and also Windows 7.
Crash occurs on the do while loop. The program does not break out of it. I have tried compiling with msvc (the latest) and also mingw-w64 and also tdm gcc. The bug is same.
The code only works on my own machine, It's not working on any other.
You need to check for more than just WSAECONNRESET. Pretty much every error (save for "would block" in non-blocking) is fatal and indicates the socket should be aborted. Don't forget that recv can and will return 0 if the remote side closes its end gracefully.
This whole loop:
do{ // IF Total is equal to expected bytes. Break the loop, And stop receiving.
fsize = recv(sockfd, recvbuf, BUFFER, 0); // Receive file
if (fsize == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
{
connected = FALSE;
printf("[X] Connection interrupted while receiving file %s for %s size.", fileinfo[0], fileinfo[1]);
}
write = WriteFile(recvfile, recvbuf, fsize, &dwBytesWritten, NULL); // Write file data to file
total += fsize; // Add number of bytes received to total.
} while(total != expected);
Should be:
do{
fsize = recv(sockfd, recvbuf, BUFFER, 0); // Receive file
if (fsize == SOCKET_ERROR) {
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK) {
// ISSUE SELECT CALL HERE TO WAIT FOR MORE DATA
}
else {
// FATAL ERROR - abort
break;
}
}
else if (fsize == 0) {
break; // remote connection terminated cleanly.
}
else {
write = WriteFile(recvfile, recvbuf, fsize, &dwBytesWritten, NULL);
total += fsize;
}
} while(total != expected);
I have resolved the issue, IT seems the problem was my own ignorance, The server side was supplying the file information too quickly, And due to that, fileinfo[] was mixed up. And thus the loop not breaking. Still don't understand why it worked on the development machine tho. Anyway, As expected the problem was not in the Code that I have posted in this Question. Thanks ya'll!
The solution was to send the data with a small time sleep. :)

C Sending files with Berkeley socket

I'm trying to send files on a Client-Server application written in c.
Client should upload files and server should receive files.
Client side :
if(fstat(fd,&file_stat) < 0){
perror("Fstat error");
return -1;
}
FILE *filepointer = fopen(filename,"rb");
if(filepointer == NULL){
perror("Opening file error");
return -1;
}
strcat(sendbuf,"8"); // option number
strcat(sendbuf,client_account.user); //user who is sending a file
strcat(sendbuf,"p1.txt"); // file name
printf("sendbuf : %s\n",sendbuf );
if(write(sock_fd,sendbuf,strlen(sendbuf)) < 0 ){
perror("Writing error");
return -1;
}
/* Check server's answer */
if((nread = read(sock_fd,buffer,sizeof(buffer))) < 0){
perror("Reading error");
return -1;
}
buffer[nread] = '\0';
printf("Buffer : %s : %d",buffer,atoi(buffer));
if(atoi(buffer) != GENERIC_OK){
printf("Error occurred\n");
return -1;
}
sprintf(file_size,"%lld",file_stat.st_size);
/* Writing file size */
if((nwritten = write(sock_fd,file_size,sizeof(file_size))) < 0){
perror("Writing error");
return -1;
}
memset(buffer,0,sizeof(buffer));
/* Check second server's answer */
if((nread = read(sock_fd,buffer,sizeof(buffer))) < 0){
perror("Reading error");
return -1;
}
buffer[nread] = '\0';
printf("Buffer : %s : %d",buffer,atoi(buffer));
if(atoi(buffer) != GENERIC_OK){
printf("Error occurred\n");
return -1;
}
while(1){
nbytes = fread(sendbuf,1,sizeof(sendbuf),filepointer);
/* There are bytes to send */
printf("Sendbuf : %s \n" , sendbuf);
if(nbytes > 0){
write(sock_fd,sendbuf,nbytes);
}
if(nbytes < 256){
if(feof(filepointer) || ferror(filepointer))
break;
}
}
Server side :
... first buffer is received well ...`
/* WRITE TO CLIENT TO CONTINUE */
if(write(sock_fd,"500",strlen("500")) < 0){ /*GENERIC OK*/
perror("Writing error");
return -1;
}
memset(recvBuf,0,sizeof(recvBuf));
/*RECEIVING FILE SIZE */
if((nread = read(sock_fd,buffer,sizeof(buffer)))< 0){
perror("Reading error");
return -1;
}
buffer[nread] = '\0';
file_size = atoi(buffer);
printf("file size : %d\n",file_size);
if((fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU)) < 0){
perror("File opening error"); /* file already exists */
}
recv_file = fopen(filename,"wb");
if(recv_file == NULL){
perror("Opening error");
return -1;
}
remaining_data = file_size;/*i think processes are blocking on while loops*/
while(((nread = read(sock_fd,recvBuf,sizeof(recvBuf))) > 0) && remaining_data > 0){
recvBuf[nread] = '\0';
printf("%d bytes received : %s \n",nread,recvBuf);
fwrite(recvBuf,1,nread,recv_file);
remaining_data -= nread;
}
if(nread < 0){
perror("Reading error");
}
I've tried to use sendfile function but I'm on Mac OS and it's not supported. Have you got any advice for me?
It should go like this :
1) client sends a buffer to server announcing it's going go send a file with its name - OK
2) server receives this buffer and sends a generic ok code to client - OK
3) client sends the size of the file to the server - OK
4) server receives this buffer and sends a generic ok code to client - OK
5) client read stuff from file and sends it to the server - NOT OK
6) server receives stuff from the client and writes stuff into the file - NOT OK
This line, in the server,
while(((nread = read(sock_fd,recvBuf,sizeof(recvBuf))) > 0) && remaining_data > 0){
is trying to read first, without having checked that remaining_data >0. The result is a read operation after all the file is transfered.
Suggest using a while(remaining_data>0) { select()/read() }, where the select() has a reasonable timeout parameter and causes an exit of the loop when a timeout occurs.
this code:
if((fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU)) < 0){
perror("File opening error"); /* file already exists */
}
recv_file = fopen(filename,"wb");
if(recv_file == NULL){
perror("Opening error");
return -1;
}
is opening the output file, in the server, twice, without an intervening close(). This is probably not what is needed.
I think you have left out some of the relevant code, but very likely the key problem is in the server's while condition:
while(((nread = read(sock_fd,recvBuf,sizeof(recvBuf))) > 0) && remaining_data > 0){
Note that it will always attempt to read data, even if it has already read the expected number of bytes. If the client holds the connection open (maybe it's waiting for a response from the server) then no EOF condition will be detected, and you have a deadlock.
Swapping the order of the conditions should resolve that problem, at least for well-behaved clients. Note, however, that even with that change, you could still get a deadlock if the client sends fewer bytes than it promises, yet holds the connection open. A malicious client could intentionally exhibit that behavior to perform a DoS against your server.
Also, 'read(sock_fd,buffer,sizeof(buffer)', followed by 'buffer[nread] = '\0';' will overflow the buffer by 1 if the the full 'sizeof(buffer)' bytes are received.
'file_size = atoi(buffer)' - not guaranteed to work since you don't know if the whole buffer has been received.
Also endianness issue with same.

socket connection getting closed abruptly with code 141

What im trying to do is connect to a remote server , read contents from a file on the local machine and send it over to the server. Then capture the server response and save it. I put the GET command in a text file and am trying get the results of the same. Here is some part of the code. Im doing this using sockets and C.
if ( inet_pton(AF_INET,ip, &(nc_args->destaddr.sin_addr.s_addr)) <= 0 )
printf("\n\t\t inet_pton error");
if (connect(sockfd, (struct sockaddr *) &nc_args->destaddr, sizeof(&nc_args->destaddr)) < 0)
{
printf("\n\t\t Connection error");
exit(1);
}
puts("\n\t\t Connection successful to ...");
// file parameter is taken from command line and passéd to this function
fp = fopen(file,"rb");
if ( fp == NULL)
{
printf("\n\t\t File not found");
exit(3);
}
else
{
printf("\n\t\t Found file %s\n", file);
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
rewind(fp);
//allocate memory to the buffer dynamically
buffer = (char*) malloc (sizeof(char)*file_size);
if (buffer == NULL) {fputs ("Memory error",stderr); exit (2);}
for (i=0 ; i<sizeof(buffer); i++)
{
printf("\n\t\t %s", buffer);
}
printf("\n\t\t File contains %ld bytes!\n", file_size);
printf("\n\t\t Sending the file now");
}
while (1)
{
bytes_read = fread(buffer,1, file_size, fp);
printf("\n\t\t The bytes read is %zd", bytes_read);
if (bytes_read == 0) // We're done reading from the file
{
printf("\n\t\t The bytes read is %zd", bytes_read);
break;
}
if (bytes_read < 0)
{
printf("\n\t\t ERROR reading from file");
}
void *p = buffer;
while (bytes_read > 0)
{
ssize_t bytes_written = send(sockfd, buffer, bytes_read,0);
if (bytes_written <= 0)
{
printf("\n\t\t ERROR writing to socket\n");
}
bytes_read -= bytes_written;
p += bytes_written;
printf("\n\t\t Bytes %zd written", bytes_written);
}
}
printf("\n\n\t\t Sending complete.");
What is happening here is that i get the message "connection successful", then it displays "sending the file now" and then the program quits unexpectedly. if i do echo $? i get 141 as the exit code. I am trying to connect from my server to a different server at work and get the results. These two can communicate correctly, and i can run the GET command from command line without issues. Its just not working from the code. Can someone let me know what the issue could be ?
On Linux, and probably other Unixes, the return code encodes a signal that the process received. Here it is 141 - 128 so 13 which corresponds to SIGPIPE.
If you don't want that signal to be raised because you capture the error return of send, anyhow, on Linux you can use MSG_NOSIGNAL in the flags argument to send to inhibit that signal. On other platforms you might have to program more complicated signal handlers to deal with that situation.
sizeof(&nc_args->destaddr) is the wrong thing to pass to connect. It wants the size of the address, not the size of a pointer to the address.
And this loop:
for (i=0 ; i<sizeof(buffer); i++)
{
printf("\n\t\t %s", buffer);
}
is baffling. buffer is a pointer, as we can see from when it was assigned a vlue returned by malloc. So its size is going to be 4 or 8 bytes on 32-bit and 64-bit architectures respectively; not related to the size of the malloc'ed object it points to. The loop runs 4 or 8 times, and prints... the same thing each time. Why?

Trying to pipe data from a child-process server to its parent process

I'm working on an assignment for my Distributed Systems class. I'm a master's student in C.S., but my specialty in programming is .NET and I'm working on a project that requires some fairly involved Unix knowledge, which is tripping me up.
The assignment is implementing a flush channel protocol API. So I'm coding a small function library that other apps can implement to use flush channel communication. I've set it up so that when the init function is called, it forks a child process to act as the server for incoming messages. The child communicates with the parent process by sending incoming data to the parent through a pipe.
This works OK if messages are sent and received one at a time; e.g.,
send -> receive -> send -> receive -> etc.
However, if multiple messages are sent before doing any receives; e.g.,
send -> send -> send -> receive
then it gets messed up. Specifically, the first message is received correctly, but when I go to receive the second message, the program hangs and needs to be killed. I've done a lot of searching online and been plugging away at this for hours but haven't made much progress.
The program as a whole is far too large to show here, but here are the most relevant bits. Here's the part where I get the server going and receive messages. Note the line
write(fd[1], buffer, (strlen(buffer)+1));
-- I think that's a good candidate for being the source of the problem here, but not sure what to do differently. (Tried fwrite() and that didn't work at all.)
fd = malloc(2 * sizeof(int));
int nbytes;
if (pipe(fd) < 0) {
perror("Could not create pipe");
return -1;
}
pID = fork();
if (pID < 0) {
perror("Failed to fork");
return -1;
} else if (pID == 0) { // child
close(fd[0]); // close input side of pipe
int cc;
int fsize;
struct sockaddr_in from;
int serials[500];
int i;
for (i = 0; i < 500; i++) serials[i] = 0;
char buffer[2048];
while (1) {
fsize = sizeof(from);
cc = recvfrom(socketNo, buffer, 2048, 0, (struct sockaddr*)&from, &fsize);
if (cc < 0) perror("Receive error");
datagram data = decodeDatagram(buffer);
if (serials[data.serial] == 0) {
write(fd[1], buffer, (strlen(buffer)+1));
serials[data.serial] = 1;
}
}
} else { // parent
close(fd[1]); // close output side of pipe
return 0;
}
(The "serials" array is for not forwarding repeated messages, as messages are sent multiple times to improve reliability. I know a fixed size for this array is not good practice, but the tests for this assignment don't send that many messages so it's OK in this context.)
The beginning of the receive function looks like this:
int fRecv(int* id, char* buf, int nbytes) {
checkDatagramTable(*id);
char* tbuf = malloc((nbytes + 9) * sizeof(char));
int rbytes = read(fd[0], tbuf, nbytes + 9);
The "+9" is to accommodate additional information that gets packaged along with the message to be sent, for flush channel ordering. This is also a pretty sketchy area, but allocating more space to be extra sure has not helped the issue.
I know there's quite a bit of extraneous stuff in here, references to other functions etc. But the problem surely lies in how I'm piping the data through, so the source of my issue should lie there somewhere.
Thanks in advance for your assistance; it is truly appreciated.
This looks suspicious. (what is in the packets? They could be binary) Where is the typedefinition for datagram ?
fsize = sizeof(from);
cc = recvfrom(socketNo, buffer, 2048, 0, (struct sockaddr*)&from, &fsize);
if (cc < 0) perror("Receive error");
datagram data = decodeDatagram(buffer);
if (serials[data.serial] == 0) {
write(fd[1], buffer, (strlen(buffer)+1)); // <-- ????
serials[data.serial] = 1;
}
I'd try instead:
write(fd[1], buffer, cc);
UPDATE:
If the message is not null terminated, you'll have to terminate it explicitly:
(if cc == 2048) cc -= 1;
buffer [cc] = '\0'; // <<--
datagram data = decodedatagram(buffer);
...
Also, it is advisable to use "sizeof buffer" instead of "2048".
UPDATE2:
You could test if the strings in the packets are really null-terminated by:
unsigned pos;
cc = recvfrom(socketNo, buffer, 2048, 0, (struct sockaddr*)&from, &fsize);
if (cc < 0) perror("Receive error");
for pos=0; pos < cc; pos++) {
if (buff[pos] == 0) break;
}
switch (cc-pos) {
case 0: fprintf (stderr, "No nul byte found in packet: I lose!\n" ); break;
default: fprintf (stderr, "Spurious nul byte found in the middle of packet\n" );
case 1: break;
}
datagram data = decodeDatagram(buffer);
if (serials[data.serial] == 0) {
write(fd[1], buffer, cc);
serials[data.serial] = 1;
}

Resources