浏览代码

Add support for IPv6 to cacaserver

tags/v0.99.beta20
Denis 9 年前
父节点
当前提交
917d506b64
共有 1 个文件被更改,包括 69 次插入44 次删除
  1. +69
    -44
      src/cacaserver.c

+ 69
- 44
src/cacaserver.c 查看文件

@@ -31,6 +31,7 @@
#endif #endif
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netdb.h>
#include <fcntl.h> #include <fcntl.h>
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
@@ -94,13 +95,19 @@ struct client
int start, stop; int start, stop;
}; };


#define MAXSOCKS 16

struct sock {
int sockfd;
struct sockaddr_in my_addr;
};

struct server struct server
{ {
unsigned int width, height; unsigned int width, height;
unsigned int port; unsigned int port;
int sockfd; int sock_count;
struct sockaddr_in my_addr; struct sock socks[MAXSOCKS];
socklen_t sin_size;


/* Input buffer */ /* Input buffer */
uint8_t *input; uint8_t *input;
@@ -118,14 +125,17 @@ struct server
RETSIGTYPE (*sigpipe_handler)(int); RETSIGTYPE (*sigpipe_handler)(int);
}; };


static void manage_connections(struct server *server); void print_ip(struct sockaddr *ai);
static void manage_connections(struct server *server, int sockfd);
static int send_data(struct server *server, struct client *c); static int send_data(struct server *server, struct client *c);
ssize_t nonblock_write(int fd, void *buf, size_t len); ssize_t nonblock_write(int fd, void *buf, size_t len);


int main(void) int main(void)
{ {
int i, yes = 1, flags; int i, yes = 1, flags, fd, error;
struct server *server; struct server *server;
struct addrinfo ai_hints, *ai, *res;
char port_str[6];
char *tmp; char *tmp;


#if USE_WINSOCK #if USE_WINSOCK
@@ -152,40 +162,39 @@ int main(void)
tmp[2] = (uint8_t) (server->height & 0xff00) >> 8; tmp[2] = (uint8_t) (server->height & 0xff00) >> 8;
tmp[3] = (uint8_t) server->height & 0xff; tmp[3] = (uint8_t) server->height & 0xff;


if((server->sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) memset(&ai_hints, 0, sizeof(ai_hints));
{ ai_hints.ai_family = AF_UNSPEC;
perror("socket"); ai_hints.ai_socktype = SOCK_STREAM;
return -1; ai_hints.ai_flags = AI_PASSIVE;
} memset(port_str, 0, sizeof(port_str));

snprintf(port_str, 6, "%d", server->port);
if(setsockopt(server->sockfd, SOL_SOCKET, error = getaddrinfo(NULL, port_str, &ai_hints, &ai);
SO_REUSEADDR, &yes, sizeof(int)) == -1) if (error)
{ perror("getaddrinfo");
perror("setsockopt SO_REUSEADDR"); for (res = ai; res && server->sock_count < MAXSOCKS; res = res->ai_next) {
return -1; if ((fd = socket(res->ai_addr->sa_family, SOCK_STREAM, 0)) == -1)
} perror("socket");

if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
server->my_addr.sin_family = AF_INET; perror("setsockopt: SO_REUSEADDR");
server-> my_addr.sin_port = htons(server->port); if (res->ai_addr->sa_family == AF_INET6)
server->my_addr.sin_addr.s_addr = INADDR_ANY; if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) == -1)
memset(&(server->my_addr.sin_zero), '\0', 8); perror("setsockopt: IPV6_V6ONLY");

if (bind(fd, res->ai_addr, res->ai_addrlen) == -1)
if(bind(server->sockfd, (struct sockaddr *)&server->my_addr, perror("bind");
sizeof(struct sockaddr)) == -1) flags = fcntl(fd, F_GETFL, 0);
{ fcntl(fd, F_SETFL, flags | O_NONBLOCK);
perror("bind"); if(listen(fd, BACKLOG) == -1)
return -1; perror("listen");

server->socks[server->sock_count].sockfd = fd;
server->sock_count++;
fprintf(stderr, "listening on ");
print_ip(res->ai_addr);
fprintf(stderr, "\n");
} }
freeaddrinfo(ai);


/* Non blocking socket */
flags = fcntl(server->sockfd, F_GETFL, 0);
fcntl(server->sockfd, F_SETFL, flags | O_NONBLOCK);

if(listen(server->sockfd, BACKLOG) == -1)
{
perror("listen");
return -1;
}


server->canvas = caca_create_canvas(0, 0); server->canvas = caca_create_canvas(0, 0);
server->buffer = NULL; server->buffer = NULL;
@@ -202,7 +211,8 @@ int main(void)
restart: restart:
/* Manage new connections as this function will be called sometimes /* Manage new connections as this function will be called sometimes
* more often than display */ * more often than display */
manage_connections(server); for (i = 0; i < server->sock_count; i++)
manage_connections(server, server->socks[i].sockfd);


/* Read data from stdin */ /* Read data from stdin */
if(server->read < 12) if(server->read < 12)
@@ -288,6 +298,9 @@ restart:
/* Restore SIGPIPE handler */ /* Restore SIGPIPE handler */
signal(SIGPIPE, server->sigpipe_handler); signal(SIGPIPE, server->sigpipe_handler);


for (i = 0; i < server->sock_count; i++)
close(server->socks[i].sockfd);

free(server); free(server);


#if USE_WINSOCK #if USE_WINSOCK
@@ -300,18 +313,30 @@ restart:
* XXX: The following functions are local * XXX: The following functions are local
*/ */


static void manage_connections(struct server *server) void print_ip(struct sockaddr *ai)
{
char buffer[INET6_ADDRSTRLEN];
int err = getnameinfo(ai, (ai->sa_family==AF_INET)?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6), buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST);
if (err != 0) {
fprintf(stderr, "n/a");
}
fprintf(stderr, "%s",buffer);
}


static void manage_connections(struct server *server, int sockfd)
{ {
int fd, flags; int fd, flags;
struct sockaddr_in remote_addr; struct sockaddr_in6 remote_addr;
socklen_t len = sizeof(struct sockaddr_in); socklen_t len = sizeof(struct sockaddr_in6);


fd = accept(server->sockfd, (struct sockaddr *)&remote_addr, &len); fd = accept(sockfd, (struct sockaddr*)&remote_addr, &len);
if(fd == -1) if(fd == -1)
return; return;


fprintf(stderr, "[%i] connected from %s\n", fprintf(stderr, "[%i] connected from ", fd);
fd, inet_ntoa(remote_addr.sin_addr)); print_ip((struct sockaddr*)&remote_addr);
fprintf(stderr, "\n");


/* Non blocking socket */ /* Non blocking socket */
flags = fcntl(fd, F_SETFL, 0); flags = fcntl(fd, F_SETFL, 0);


||||||
x
 
000:0
正在加载...
取消
保存