Discussion:
[PATCH 1/3] fix TCP/IP networking protocol
Johannes Weißl
2011-05-11 19:03:40 UTC
Permalink
it was not working before for me
---
main.c | 27 +++++++++++++++------------
server.c | 44 ++++++++++++++++++++++++++++++++++----------
server.h | 1 +
3 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/main.c b/main.c
index 3f0ea39..0b2c19f 100644
--- a/main.c
+++ b/main.c
@@ -57,7 +57,7 @@ static void gethostbyname_failed(void)
die("gethostbyname: %s\n", error);
}

-static void read_answer(void)
+static int read_answer(void)
{
char buf[8192];
int got_nl = 0;
@@ -68,7 +68,7 @@ static void read_answer(void)

if (rc < 0) {
warn_errno("read");
- return;
+ break;
}
if (!rc)
die("unexpected EOF\n");
@@ -78,27 +78,28 @@ static void read_answer(void)
// Last line should be empty (i.e. read "\n" or "...\n\n").
// Write everything but the last \n to stdout.
if (got_nl && buf[0] == '\n')
- return;
+ break;
if (len == 1 && buf[0] == '\n')
- return;
+ break;
if (rc > 1 && buf[rc - 1] == '\n' && buf[rc - 2] == '\n') {
write_all(1, buf, rc - 1);
- return;
+ break;
}
got_nl = buf[rc - 1] == '\n';
write_all(1, buf, rc);
}
+ return len;
}

-static void write_line(const char *line)
+static int write_line(const char *line)
{
if (write_all(sock, line, strlen(line)) == -1)
die_errno("write");

- read_answer();
+ return read_answer();
}

-static void send_cmd(const char *format, ...)
+static int send_cmd(const char *format, ...)
{
char buf[512];
va_list ap;
@@ -107,10 +108,10 @@ static void send_cmd(const char *format, ...)
vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);

- write_line(buf);
+ return write_line(buf);
}

-static void remote_connect(const char *address)
+static int remote_connect(const char *address)
{
union {
struct sockaddr sa;
@@ -172,7 +173,8 @@ static void remote_connect(const char *address)
}

if (passwd)
- send_cmd("%s\n", passwd);
+ return send_cmd("passwd %s\n", passwd) == 1;
+ return 1;
}

static char *file_url_absolute(const char *str)
@@ -380,7 +382,8 @@ int main(int argc, char *argv[])
server = server_buf;
}

- remote_connect(server);
+ if (!remote_connect(server))
+ return 1;

if (raw_args) {
while (*argv)
diff --git a/server.c b/server.c
index 2d4e231..48579f7 100644
--- a/server.c
+++ b/server.c
@@ -33,6 +33,7 @@
#include "misc.h"
#include "keyval.h"

+#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -127,11 +128,24 @@ static int cmd_status(struct client *client)
return ret;
}

+static ssize_t send_answer(int fd, const char *format, ...)
+{
+ char buf[512];
+ va_list ap;
+
+ va_start(ap, format);
+ vsnprintf(buf, sizeof(buf), format, ap);
+ va_end(ap);
+
+ return write_all(fd, buf, strlen(buf));
+}
+
static void read_commands(struct client *client)
{
char buf[1024];
int pos = 0;
- int authenticated = addr.sa.sa_family == AF_UNIX;
+ if (!client->authenticated)
+ client->authenticated = addr.sa.sa_family == AF_UNIX;

while (1) {
int rc, s, i;
@@ -150,7 +164,7 @@ static void read_commands(struct client *client)

s = 0;
for (i = 0; i < pos; i++) {
- const char *line;
+ const char *line, *msg;
char *cmd, *arg;
int ret;

@@ -161,16 +175,23 @@ static void read_commands(struct client *client)
line = buf + s;
s = i + 1;

- if (!authenticated) {
+ if (!client->authenticated) {
if (!server_password) {
- d_print("password is unset, tcp/ip disabled\n");
+ msg = "password is unset, tcp/ip disabled";
+ d_print("%s\n", msg);
+ ret = send_answer(client->fd, "%s\n\n", msg);
goto close;
}
- authenticated = !strcmp(line, server_password);
- if (!authenticated) {
- d_print("authentication failed\n");
+ if (strncmp(line, "passwd ", 7) == 0)
+ line += 7;
+ client->authenticated = !strcmp(line, server_password);
+ if (!client->authenticated) {
+ msg = "authentication failed";
+ d_print("%s\n", msg);
+ ret = send_answer(client->fd, "%s\n\n", msg);
goto close;
}
+ ret = write_all(client->fd, "\n", 1);
continue;
}

@@ -201,9 +222,11 @@ static void read_commands(struct client *client)
if (!strcmp(cmd, "status")) {
ret = cmd_status(client);
} else {
- set_client_fd(client->fd);
- run_parsed_command(cmd, arg);
- set_client_fd(-1);
+ if (strcmp(cmd, "passwd") != 0) {
+ set_client_fd(client->fd);
+ run_parsed_command(cmd, arg);
+ set_client_fd(-1);
+ }
ret = write_all(client->fd, "\n", 1);
}
free(cmd);
@@ -242,6 +265,7 @@ void server_accept(void)

client = xnew(struct client, 1);
client->fd = fd;
+ client->authenticated = 0;
list_add_tail(&client->node, &client_head);
}

diff --git a/server.h b/server.h
index cd6d900..9f1e55d 100644
--- a/server.h
+++ b/server.h
@@ -24,6 +24,7 @@
struct client {
struct list_head node;
int fd;
+ unsigned int authenticated : 1;
};

extern int server_socket;
--
1.7.5.1
Johannes Weißl
2011-05-11 19:03:41 UTC
Permalink
Simplify and generalize, as a side effect it works now with IPv6!
---
http.c | 28 +++++++++++++++++-----------
main.c | 56 ++++++++++++++++++--------------------------------------
server.c | 59 +++++++++++++++++++----------------------------------------
utils.h | 3 +++
4 files changed, 57 insertions(+), 89 deletions(-)

diff --git a/http.c b/http.c
index b504ad1..ef7a494 100644
--- a/http.c
+++ b/http.c
@@ -22,6 +22,7 @@
#include "xmalloc.h"
#include "gbuf.h"

+#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
@@ -133,13 +134,19 @@ void http_free_uri(struct http_uri *u)

int http_open(struct http_get *hg, int timeout_ms)
{
- struct hostent *hostent;
+ const struct addrinfo hints = {
+ .ai_socktype = SOCK_STREAM
+ };
+ struct addrinfo *result;
union {
struct sockaddr sa;
struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage sas;
} addr;
struct timeval tv;
- int save, flags;
+ int save, flags, rc;
+ char port[16];

char *proxy = getenv("http_proxy");
if (proxy) {
@@ -152,15 +159,16 @@ int http_open(struct http_get *hg, int timeout_ms)
hg->proxy = NULL;
}

- hostent = gethostbyname(hg->proxy ? hg->proxy->host : hg->uri.host);
- if (hostent == NULL)
+ snprintf(port, sizeof(port), "%d", hg->proxy ? hg->proxy->port : hg->uri.port);
+ rc = getaddrinfo(hg->proxy ? hg->proxy->host : hg->uri.host, port, &hints, &result);
+ if (rc != 0) {
+ d_print("getaddrinfo: %s\n", gai_strerror(rc));
return -1;
+ }
+ memcpy(&addr.sa, result->ai_addr, result->ai_addrlen);
+ freeaddrinfo(result);

- addr.in.sin_family = AF_INET;
- addr.in.sin_port = htons(hg->proxy ? hg->proxy->port : hg->uri.port);
- memcpy(&addr.in.sin_addr, hostent->h_addr_list[0], hostent->h_length);
-
- hg->fd = socket(PF_INET, SOCK_STREAM, 0);
+ hg->fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
if (hg->fd == -1)
return -1;

@@ -184,8 +192,6 @@ int http_open(struct http_get *hg, int timeout_ms)
FD_ZERO(&wfds);
FD_SET(hg->fd, &wfds);
while (1) {
- int rc;
-
rc = select(hg->fd + 1, NULL, &wfds, NULL, &tv);
if (rc == -1) {
if (errno != EINTR)
diff --git a/main.c b/main.c
index 0b2c19f..76924f2 100644
--- a/main.c
+++ b/main.c
@@ -20,6 +20,7 @@
#include "file.h"
#include "path.h"
#include "xmalloc.h"
+#include "utils.h"

#include <unistd.h>
#include <fcntl.h>
@@ -38,25 +39,6 @@ static int sock;
static int raw_args = 0;
static char *passwd;

-static void gethostbyname_failed(void)
-{
- const char *error = "Unknown error.";
-
- switch (h_errno) {
- case HOST_NOT_FOUND:
- case NO_DATA:
- error = "Host not found.";
- break;
- case NO_RECOVERY:
- error = "A non-recoverable name server error.";
- break;
- case TRY_AGAIN:
- error = "A temporary error occurred on an authoritative name server.";
- break;
- }
- die("gethostbyname: %s\n", error);
-}
-
static int read_answer(void)
{
char buf[8192];
@@ -117,8 +99,10 @@ static int remote_connect(const char *address)
struct sockaddr sa;
struct sockaddr_un un;
struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage sas;
} addr;
- int addrlen;
+ size_t addrlen;

if (strchr(address, '/')) {
if (passwd)
@@ -130,32 +114,28 @@ static int remote_connect(const char *address)

addrlen = sizeof(addr.un);
} else {
- char *s = strchr(address, ':');
- int port = DEFAULT_PORT;
- struct hostent *hent;
+ const struct addrinfo hints = {
+ .ai_socktype = SOCK_STREAM
+ };
+ const char *port = STRINGIZE(DEFAULT_PORT);
+ struct addrinfo *result;
+ char *s = strrchr(address, ':');
+ int rc;

if (!passwd)
die("password required for tcp/ip connection\n");

if (s) {
*s++ = 0;
- port = atoi(s);
+ port = s;
}
- hent = gethostbyname(address);
- if (!hent)
- gethostbyname_failed();

- addr.sa.sa_family = hent->h_addrtype;
- switch (addr.sa.sa_family) {
- case AF_INET:
- memcpy(&addr.in.sin_addr, hent->h_addr_list[0], hent->h_length);
- addr.in.sin_port = htons(port);
-
- addrlen = sizeof(addr.in);
- break;
- default:
- die("unsupported address type\n");
- }
+ rc = getaddrinfo(address, port, &hints, &result);
+ if (rc != 0)
+ die("getaddrinfo: %s\n", gai_strerror(rc));
+ memcpy(&addr.sa, result->ai_addr, result->ai_addrlen);
+ addrlen = result->ai_addrlen;
+ freeaddrinfo(result);
}

sock = socket(addr.sa.sa_family, SOCK_STREAM, 0);
diff --git a/server.c b/server.c
index 48579f7..892338e 100644
--- a/server.c
+++ b/server.c
@@ -56,6 +56,8 @@ static union {
struct sockaddr sa;
struct sockaddr_un un;
struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage sas;
} addr;

#define MAX_CLIENTS 10
@@ -277,29 +279,10 @@ void server_serve(struct client *client)
run_only_safe_commands = 0;
}

-static void gethostbyname_failed(void)
-{
- const char *error = "Unknown error.";
-
- switch (h_errno) {
- case HOST_NOT_FOUND:
- case NO_DATA:
- error = "Host not found.";
- break;
- case NO_RECOVERY:
- error = "A non-recoverable name server error.";
- break;
- case TRY_AGAIN:
- error = "A temporary error occurred on an authoritative name server.";
- break;
- }
- die("gethostbyname: %s\n", error);
-}
-
void server_init(char *address)
{
- int port = DEFAULT_PORT;
- int addrlen;
+ const char *port = STRINGIZE(DEFAULT_PORT);
+ size_t addrlen;

if (strchr(address, '/')) {
addr.sa.sa_family = AF_UNIX;
@@ -307,28 +290,24 @@ void server_init(char *address)

addrlen = sizeof(struct sockaddr_un);
} else {
- char *s = strchr(address, ':');
- struct hostent *hent;
+ const struct addrinfo hints = {
+ .ai_socktype = SOCK_STREAM
+ };
+ struct addrinfo *result;
+ char *s = strrchr(address, ':');
+ int rc;

if (s) {
*s++ = 0;
- port = atoi(s);
- }
- hent = gethostbyname(address);
- if (!hent)
- gethostbyname_failed();
-
- addr.sa.sa_family = hent->h_addrtype;
- switch (addr.sa.sa_family) {
- case AF_INET:
- memcpy(&addr.in.sin_addr, hent->h_addr_list[0], hent->h_length);
- addr.in.sin_port = htons(port);
-
- addrlen = sizeof(addr.in);
- break;
- default:
- die("unsupported address type\n");
+ port = s;
}
+
+ rc = getaddrinfo(address, port, &hints, &result);
+ if (rc != 0)
+ die("getaddrinfo: %s\n", gai_strerror(rc));
+ memcpy(&addr.sa, result->ai_addr, result->ai_addrlen);
+ addrlen = result->ai_addrlen;
+ freeaddrinfo(result);
}

server_socket = socket(addr.sa.sa_family, SOCK_STREAM, 0);
@@ -343,7 +322,7 @@ void server_init(char *address)

/* address already in use */
if (addr.sa.sa_family != AF_UNIX)
- die("cmus is already listening on %s:%d\n", address, port);
+ die("cmus is already listening on %s:%s\n", address, port);

/* try to connect to server */
sock = socket(AF_UNIX, SOCK_STREAM, 0);
diff --git a/utils.h b/utils.h
index f625462..c48ea35 100644
--- a/utils.h
+++ b/utils.h
@@ -34,6 +34,9 @@

#define N_ELEMENTS(array) (sizeof(array) / sizeof((array)[0]))

+#define STRINGIZE_HELPER(x) #x
+#define STRINGIZE(x) STRINGIZE_HELPER(x)
+
#define getentry(ptr, offset, type) (*((type *) ((char *) (ptr) + (offset))))

static inline int min(int a, int b)
--
1.7.5.1
Johannes Weißl
2011-05-11 19:54:21 UTC
Permalink
---
http.c | 6 +++---
main.c | 2 --
server.c | 2 --
3 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/http.c b/http.c
index ef7a494..61c3677 100644
--- a/http.c
+++ b/http.c
@@ -140,10 +140,9 @@ int http_open(struct http_get *hg, int timeout_ms)
struct addrinfo *result;
union {
struct sockaddr sa;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
struct sockaddr_storage sas;
} addr;
+ size_t addrlen;
struct timeval tv;
int save, flags, rc;
char port[16];
@@ -166,6 +165,7 @@ int http_open(struct http_get *hg, int timeout_ms)
return -1;
}
memcpy(&addr.sa, result->ai_addr, result->ai_addrlen);
+ addrlen = result->ai_addrlen;
freeaddrinfo(result);

hg->fd = socket(addr.sa.sa_family, SOCK_STREAM, 0);
@@ -182,7 +182,7 @@ int http_open(struct http_get *hg, int timeout_ms)
fd_set wfds;

d_print("connecting. timeout=%lld s %lld us\n", (long long)tv.tv_sec, (long long)tv.tv_usec);
- if (connect(hg->fd, &addr.sa, sizeof(addr.in)) == 0)
+ if (connect(hg->fd, &addr.sa, addrlen) == 0)
break;
if (errno == EISCONN)
break;
diff --git a/main.c b/main.c
index 76924f2..d3c5e0a 100644
--- a/main.c
+++ b/main.c
@@ -98,8 +98,6 @@ static int remote_connect(const char *address)
union {
struct sockaddr sa;
struct sockaddr_un un;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
struct sockaddr_storage sas;
} addr;
size_t addrlen;
diff --git a/server.c b/server.c
index 892338e..d09f74b 100644
--- a/server.c
+++ b/server.c
@@ -55,8 +55,6 @@ LIST_HEAD(client_head);
static union {
struct sockaddr sa;
struct sockaddr_un un;
- struct sockaddr_in in;
- struct sockaddr_in6 in6;
struct sockaddr_storage sas;
} addr;
--
1.7.5.1
Johannes Weißl
2011-05-11 19:03:42 UTC
Permalink
on older systems, check for string function only works correctly if
<string.h> is included. Otherwise compilation fails.
---
configure | 23 +++++++++++++++++++++--
1 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 29bb911..b565e47 100755
--- a/configure
+++ b/configure
@@ -331,6 +331,25 @@ check_ffmpeg()
return 0
}

+check_string_function()
+{
+ msg_checking "for function $1"
+ string_function_code="
+#include <string.h>
+int main() {
+ return $1;
+}
+"
+ if try_compile_link "$string_function_code"
+ then
+ msg_result yes
+ return 0
+ fi
+ msg_result no
+ return 1
+}
+
+
# defaults
prefix=/usr/local
DEBUG=1
@@ -408,8 +427,8 @@ check check_rtsched
check check_ncurses
check check_iconv
check_header byteswap.h && HAVE_BYTESWAP_H=y
-check_function "strdup" && HAVE_STRDUP=y
-check_function "strndup" && HAVE_STRNDUP=y
+check_string_function "strdup" && HAVE_STRDUP=y
+check_string_function "strndup" && HAVE_STRNDUP=y

check check_flac CONFIG_FLAC
check check_mad CONFIG_MAD
--
1.7.5.1
Gregory Petrosyan
2011-05-13 08:04:31 UTC
Permalink
Post by Johannes Weißl
it was not working before for me
---
main.c | 27 +++++++++++++++------------
server.c | 44 ++++++++++++++++++++++++++++++++++----------
server.h | 1 +
3 files changed, 50 insertions(+), 22 deletions(-)
Thanks, merged all 3!

Gregory

Loading...