netcat: Rewrite the i/o loop

* Stop echoing back the input.
  It isn't the responsibility of this app, IMO.

* Allow non-text data

* Error checks and cleanups
This commit is contained in:
YAMAMOTO Takashi 2021-01-28 09:57:06 +09:00 committed by Xiang Xiao
parent 8093aa7487
commit eb996e5650

View File

@ -24,8 +24,9 @@
****************************************************************************/ ****************************************************************************/
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@ -45,12 +46,44 @@
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
int do_io(int infd, int outfd)
{
size_t capacity = 256;
char buf[capacity];
while (true)
{
ssize_t avail = read(infd, buf, capacity);
if (avail == 0)
{
break;
}
if (avail == -1)
{
perror("do_io: read error");
return 5;
}
ssize_t written = write(outfd, buf, avail);
if (written == -1)
{
perror("do_io: write error");
return 6;
}
}
return EXIT_SUCCESS;
}
int netcat_server(int argc, char * argv[]) int netcat_server(int argc, char * argv[])
{ {
FILE * fout = stdout; int id = -1;
int outfd = STDOUT_FILENO;
struct sockaddr_in server; struct sockaddr_in server;
struct sockaddr_in client; struct sockaddr_in client;
int port = NETCAT_PORT; int port = NETCAT_PORT;
int result = EXIT_SUCCESS;
if ((1 < argc) && (0 == strcmp("-l", argv[1]))) if ((1 < argc) && (0 == strcmp("-l", argv[1])))
{ {
@ -61,21 +94,23 @@ int netcat_server(int argc, char * argv[])
if (3 < argc) if (3 < argc)
{ {
fout = fopen(argv[3], "w"); outfd = open(argv[3], O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (0 > fout) if (outfd == -1)
{ {
perror("error: io: Failed to create file"); perror("error: io: Failed to create file");
return 1; outfd = STDOUT_FILENO;
result = 1;
goto out;
} }
} }
} }
int id;
id = socket(AF_INET , SOCK_STREAM , 0); id = socket(AF_INET , SOCK_STREAM , 0);
if (0 > id) if (0 > id)
{ {
perror("error: net: Failed to create socket"); perror("error: net: Failed to create socket");
return 2; result = 2;
goto out;
} }
server.sin_family = AF_INET; server.sin_family = AF_INET;
@ -84,49 +119,57 @@ int netcat_server(int argc, char * argv[])
if (0 > bind(id, (struct sockaddr *)&server , sizeof(server))) if (0 > bind(id, (struct sockaddr *)&server , sizeof(server)))
{ {
perror("error: net: Failed to bind"); perror("error: net: Failed to bind");
return 3; result = 3;
goto out;
} }
fprintf(stderr, "log: net: listening on :%d\n", port); fprintf(stderr, "log: net: listening on :%d\n", port);
listen(id , 3); if (listen(id , 3) == -1)
int capacity = 256; {
char buf[capacity]; perror("error: net: Failed to listen");
result = 7;
goto out;
}
socklen_t addrlen; socklen_t addrlen;
int conn; int conn;
while ((conn = accept(id, (struct sockaddr *)&client, &addrlen))) while ((conn = accept(id, (struct sockaddr *)&client, &addrlen)) != -1)
{ {
int avail = 1; result = do_io(conn, outfd);
while (0 < avail) if (result != 0)
{ {
avail = recv(conn, buf, capacity, 0); break;
fwrite(buf, avail, 1, fout);
int status = fflush(fout);
if (0 != status)
{
perror("error: io: Failed to flush");
}
} }
} }
if (0 > conn) if (0 > conn)
{ {
perror("accept failed"); perror("accept failed");
return 4; result = 4;
goto out;
} }
if (stdout != fout) out:
if (id != -1)
{ {
fclose(fout); close(id);
} }
return EXIT_SUCCESS; if (outfd != STDOUT_FILENO)
{
close(outfd);
}
return result;
} }
int netcat_client(int argc, char * argv[]) int netcat_client(int argc, char * argv[])
{ {
FILE *fin = stdin; int id = -1;
int infd = STDIN_FILENO;
char *host = "127.0.0.1"; char *host = "127.0.0.1";
int port = NETCAT_PORT; int port = NETCAT_PORT;
int result = EXIT_SUCCESS;
if (argc > 1) if (argc > 1)
{ {
@ -140,20 +183,22 @@ int netcat_client(int argc, char * argv[])
if (argc > 3) if (argc > 3)
{ {
fin = fopen(argv[3], "r"); infd = open(argv[3], O_RDONLY);
if (0 > fin) if (infd == -1)
{ {
perror("error: io: Failed to create file"); perror("error: io: Failed to open file");
return 1; infd = STDIN_FILENO;
result = 1;
goto out;
} }
} }
int id;
id = socket(AF_INET , SOCK_STREAM , 0); id = socket(AF_INET , SOCK_STREAM , 0);
if (0 > id) if (0 > id)
{ {
perror("error: net: Failed to create socket"); perror("error: net: Failed to create socket");
return 2; result = 2;
goto out;
} }
struct sockaddr_in server; struct sockaddr_in server;
@ -162,47 +207,31 @@ int netcat_client(int argc, char * argv[])
if (1 != inet_pton(AF_INET, host, &server.sin_addr)) if (1 != inet_pton(AF_INET, host, &server.sin_addr))
{ {
perror("error: net: Invalid host"); perror("error: net: Invalid host");
return 3; result = 3;
goto out;
} }
if (connect(id, (struct sockaddr *) &server, sizeof(server)) < 0) if (connect(id, (struct sockaddr *) &server, sizeof(server)) < 0)
{ {
perror("error: net: Failed to connect"); perror("error: net: Failed to connect");
return 4; result = 4;
goto out;
} }
int capacity = 256; result = do_io(infd, id);
char buf[capacity];
int avail; out:
while (true) if (id != -1)
{ {
avail = -1; close(id);
if (fgets(buf, capacity, fin))
{
avail = strnlen(buf, capacity);
}
if (avail < 0)
{
exit(EXIT_SUCCESS);
}
buf[avail] = 0;
avail = write(id, buf, avail);
printf("%s", buf);
if (avail < 0)
{
perror("error: net: writing to socket");
exit(1);
}
} }
if (stdout != fin) if (infd != STDIN_FILENO)
{ {
fclose(fin); close(infd);
} }
return EXIT_SUCCESS; return result;
} }
/**************************************************************************** /****************************************************************************