commit 5d911a560f6c8664dd93556b222f3b95bb36216d
parent 90e042484d278970be026777d54b81661efd3938
Author: dsp <dsp@2f30.org>
Date: Tue, 19 Jun 2012 01:14:41 +0300
changed the way nbeng works , now utilizing only one socket.
removed assl dependencies, soon we will provide our custom ssl wrapper.
removed tcp code, just created placeholder.
general cleanup and comments.
Diffstat:
8 files changed, 156 insertions(+), 82 deletions(-)
diff --git a/Makefile b/Makefile
@@ -8,9 +8,8 @@ CC = gcc
INCS = -I/usr/local/include
LIBS = -L/usr/local/lib
-CFLAGS += -Wall -Wextra -Wunused -DVERSION=\"${VER}\" ${INCS}
-#add assl
-#LDFLAGS += -lassl ${LIBS}
+CFLAGS += -Wall -Wextra -Wunused -g -DVERSION=\"${VER}\" ${INCS}
+LDFLAGS += ${LIBS}
$(BIN): ${OBJ}
${CC} ${CFLAGS} ${LDFLAGS} -o $@ ${OBJ}
@@ -19,6 +18,6 @@ $(BIN): ${OBJ}
${CC} ${CFLAGS} -c -o $@ $<
clean:
- rm -rf ${BIN} ${OBJ}
+ rm -rf ${BIN} ${OBJ} *.core
all: nbeng
diff --git a/README b/README
@@ -1,8 +1,15 @@
-NonBlockingENGine by <dsp@2f30.org>
+NonBlockingENGine by <dsp@2f30.org>,<lostd@2f30.org>
A nonblocking client/server engine for future use on sscall.
(https://github.com/quantumdream/sscall.git)
-Will support SSL connections via ASSL.
+Will support SSL connections via a custom SSL wrapper.
+For SSL you have to create and sign certificates and keys
+by running the scripts in the ssl/ directory.
+
+cd ssl/; sh create_ca; sh create_client; sh create_server;
+sh sign_client; sh sign_server;
+
to test get a netcat proccess listening for udp on a port:
-nc -ul 127.0.0.1 8888
-./nbeng 127.0.0.1 8888 1234
+(BOX1) nc -ul 8888 (see the data that BOX2 sends)
+(BOX2) ./nbeng BOX1 8888 (send data to BOX1 and recv from it)
+(BOX1) nc -u BOX2 (send data to BOX2)
diff --git a/nbeng.c b/nbeng.c
@@ -1,3 +1,12 @@
+/*
+ * NonBlocking network engine for tcp/udp/ssl connections
+ * The design uses the same socket for sending and receiving
+ * data. The relevant data are stored in a connection context
+ * which is passed around the funcs for dealing with it.
+ * Also provided are 2 sample reading and writing functions.
+ * CopyLeft: (DsP <dsp@2f30.org>, lostd <lostd@2f30.org>)
+ * cheers go to photorec for helping recover this file :)
+ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -11,95 +20,116 @@
#include <sys/time.h>
#include <fcntl.h>
#include <err.h>
+#include <errno.h>
-/* SSL flag */
-int fssl = 0;
+/* TCP flag */
+unsigned int ftcp = 0;
+
+/* flag to know when to quit the prog */
+unsigned int quitflag=0;
/* connection context */
typedef struct concontxt_t {
- int clifd; /* client fd */
- int srvfd; /* server fd */
- struct addrinfo *clinfo;
- struct addrinfo *srvinfo;
+ int confd; /* net connection fd */
+ struct addrinfo *clinfo; /* info on where we connect */
+ struct addrinfo *srvinfo; /* info for the local part */
} concontxt;
static void
usage(const char *s)
{
fprintf(stderr, "usage: %s [OPTIONS] "
- "<remote-addr> <remote-port> <local-port>\n", s);
- fprintf(stderr, " -s\tSSL on\n");
+ "<remote-addr> <remote-port>\n", s);
+ fprintf(stderr, " -t\ttcp session\n");
fprintf(stderr, " -h\tThis help screen\n");
}
-/* connect to in port port and store the fds in the context */
static void
-connectit(concontxt *c, char *to, char *port)
+set_nonblocking(int fd)
{
- struct addrinfo cli_hints, *cli_servinfo, *p0;
- int rv, cli_sockfd;
- if ((c == NULL) || (to == NULL) || (port == NULL))
- errx(1, "conectit was passed a null arg");
- memset(&cli_hints, 0, sizeof(cli_hints));
- cli_hints.ai_family = AF_INET;
- cli_hints.ai_socktype = SOCK_DGRAM;
- rv = getaddrinfo(to, port, &cli_hints, &cli_servinfo);
- if (rv)
- errx(1, "getaddrinfo: %s", gai_strerror(rv));
+ int opts;
+ opts = fcntl(fd, F_GETFL);
+ if (opts < 0)
+ err(1, "fcntl");
+ opts = (opts | O_NONBLOCK);
+ if (fcntl(fd, F_SETFL, opts) < 0)
+ err(1, "fcntl");
+}
- for (p0 = cli_servinfo; p0; p0 = p0->ai_next) {
- cli_sockfd = socket(p0->ai_family, p0->ai_socktype,
- p0->ai_protocol);
- if (cli_sockfd < 0)
- continue;
- break;
- }
- if (!p0)
- errx(1, "failed to bind socket");
- /* all was ok, so we register the socket to the context */
- c->clifd = cli_sockfd;
- c->clinfo = cli_servinfo;
+static void
+set_blocking(int fd)
+{
+ int opts;
+ opts = fcntl(fd, F_GETFL);
+ if (opts < 0)
+ err(1, "fcntl");
+ opts &= (~O_NONBLOCK);
+ if (fcntl(fd, F_SETFL, opts) < 0)
+ err(1, "fcntl");
}
+/*
+ * This is the main function that prepares a socket for
+ * a) connection to the other endpoint.
+ * b) being able to receive data.
+ * when it is ready it sets the fields in the context.
+ * XXX: add a flag in the parameter list for type (tcp/udp/ssl)
+ */
static void
-serveit(concontxt *c, char *port)
-{
- struct addrinfo srv_hints, *srv_servinfo, *p0;
- int rv, srv_sockfd,optval;
+prepare_socket(concontxt *c, char *to, char *port)
+{
+ struct addrinfo cli_hints, *cli_servinfo, srv_hints, *srv_servinfo, *p0;
+ int rv, cli_sockfd,optval=1;
+ if ((c == NULL) || (to == NULL) || (port == NULL))
+ errx(1, "prepare_socket was passed a null arg");
+ memset(&cli_hints, 0, sizeof(cli_hints));
memset(&srv_hints, 0, sizeof(srv_hints));
- srv_hints.ai_family = AF_INET;
- srv_hints.ai_socktype = SOCK_DGRAM;
- srv_hints.ai_flags = AI_PASSIVE;
+ cli_hints.ai_family = srv_hints.ai_family = AF_INET;
+ cli_hints.ai_socktype = srv_hints.ai_socktype = ftcp ? SOCK_STREAM : SOCK_DGRAM;
+ rv = getaddrinfo(to, port, &cli_hints, &cli_servinfo);
+ if (rv)
+ errx(1, "getaddrinfo: %s", gai_strerror(rv));
rv = getaddrinfo(NULL, port, &srv_hints, &srv_servinfo);
if (rv)
errx(1, "getaddrinfo: %s", gai_strerror(rv));
- for(p0 = srv_servinfo; p0; p0 = p0->ai_next) {
- srv_sockfd = socket(p0->ai_family, p0->ai_socktype,
+ /* getaddrinfo returns a list of results so we iterate on it */
+ for (p0 = cli_servinfo; p0; p0 = p0->ai_next) {
+ cli_sockfd = socket(p0->ai_family, p0->ai_socktype,
p0->ai_protocol);
- if (srv_sockfd < 0)
- continue;
- optval = 1;
- rv = setsockopt(srv_sockfd, SOL_SOCKET,
+ if (cli_sockfd < 0)
+ continue; /* until the socket is ready */
+ rv = setsockopt(cli_sockfd, SOL_SOCKET,
SO_REUSEADDR, &optval, sizeof(optval));
if (rv < 0) {
- close(srv_sockfd);
+ close(cli_sockfd);
warn("setsockopt");
continue;
}
- if (bind(srv_sockfd, p0->ai_addr, p0->ai_addrlen) < 0) {
- close(srv_sockfd);
- warn("bind");
- continue;
+ break;
+ }
+ if (!p0)
+ errx(1, "failed to create socket");
+ /* the same for our local part */
+ for (p0 = srv_servinfo; p0; p0 = p0->ai_next) {
+ if (bind(cli_sockfd, p0->ai_addr, p0->ai_addrlen) < 0) {
+ close(cli_sockfd);
+ warn("bind");
+ continue;
}
break;
}
if (!p0)
errx(1, "failed to bind socket");
- /* register them to the context */
- c->srvfd = srv_sockfd;
- c->srvinfo = srv_servinfo;
+ /* all was ok, so we register the socket to the context */
+ c->confd = cli_sockfd;
+ c->clinfo = cli_servinfo;
}
+/*
+ * this sample func reads data from input, null-terminates them
+ * and sends them over the prepared socket stored in the context.
+ * If it gets a "Q" it quits.
+ */
static void
stdinputdata(concontxt *con)
{ char *inbuf = NULL, *linbuf = NULL;
@@ -123,16 +153,26 @@ stdinputdata(concontxt *con)
if ((strncmp(inbuf, "Q", 2) == 0))
goto freex;
printf("got msg: %s , sending it\n", inbuf);
- sendto(con->clifd, inbuf, inbufln, 0,
- con->clinfo->ai_addr,
- con->clinfo->ai_addrlen);
+ if (ftcp == 0) {
+ sendto(con->confd, inbuf, inbufln, 0,
+ con->clinfo->ai_addr,
+ con->clinfo->ai_addrlen);
+ } else {
+ /* code for tcp */
+ }
fflush(stdout);
/* free the buf */
freex:
if(linbuf != NULL)
free(linbuf);
+ /* let the main process know we want out */
+ quitflag=1;
}
+/*
+ * This sample receive func, reads up to 512 bytes of input
+ * from the socket stored in the context.
+ */
static void
srvinputdata(concontxt *con)
{
@@ -143,10 +183,14 @@ srvinputdata(concontxt *con)
socklen_t addr_len;
struct sockaddr_storage their_addr;
addr_len = sizeof(their_addr);
- bytes = recvfrom(con->srvfd, buf,
- sizeof(buf), MSG_DONTWAIT,
- (struct sockaddr *)&their_addr,
- &addr_len);
+ if (ftcp == 0) {
+ bytes = recvfrom(con->confd, buf,
+ sizeof(buf), MSG_DONTWAIT,
+ (struct sockaddr *)&their_addr,
+ &addr_len);
+ } else {
+ /* code for tcp */
+ }
if (bytes > 0) {
ret = getnameinfo((struct sockaddr *)&their_addr,
addr_len, host,
@@ -159,6 +203,7 @@ srvinputdata(concontxt *con)
}
}
+
int
main(int argc, char *argv[])
{
@@ -170,14 +215,14 @@ main(int argc, char *argv[])
int highsock, readsocks;
struct timeval timeout;
concontxt *con = (concontxt *) malloc(sizeof (concontxt));
- while ((c = getopt(argc, argv, "hs")) != -1) {
+ while ((c = getopt(argc, argv, "ht")) != -1) {
switch (c) {
case 'h':
usage(prog);
goto freex;
break;
- case 's':
- fssl = 1;
+ case 't':
+ ftcp = 1;
break;
case '?':
default:
@@ -187,21 +232,24 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (argc != 3) {
+ if (argc != 2) {
usage(prog);
goto freex;
}
- /* connect to the host */
- connectit(con, argv[0], argv[1]);
- /* prepare the server socket */
- serveit(con, argv[2]);
- /* XXX: this should change when we add the srv fd */
- highsock = con->srvfd;
- /* these are the sockets for reading (stdin + server fd) */
+ if (ftcp == 0) {
+ /* prepare the socket for udp */
+ prepare_socket(con, argv[0], argv[1]);
+ } else {
+ /* code for tcp */
+ }
+ highsock = con->confd;
+ /* these are the sockets for reading (stdin + connection fd) */
while (1) {
+ if (quitflag)
+ goto freex;
FD_ZERO(&rsocks);
FD_SET(recfd, &rsocks);
- FD_SET(con->srvfd, &rsocks);
+ FD_SET(con->confd, &rsocks);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
readsocks = select(highsock + 1, &rsocks, (fd_set *)0,
@@ -218,15 +266,16 @@ main(int argc, char *argv[])
if (FD_ISSET(recfd, &rsocks)) {
stdinputdata(con);
}
- if (FD_ISSET(con->srvfd,&rsocks)) {
+ if (FD_ISSET(con->confd, &rsocks)) {
srvinputdata(con);
}
}
}
freex:
+ printf("exiting\n");
if (con != NULL) {
- close(con->clifd);
+ close(con->confd);
free(con);
}
return (0);
diff --git a/ssl/create_ca b/ssl/create_ca
@@ -0,0 +1,5 @@
+#/bin/sh
+
+mkdir -p ca/private
+chmod 700 ca/private
+openssl req -x509 -days 3650 -newkey rsa:1024 -keyout ca/private/ca.key -out ca/ca.crt
diff --git a/ssl/create_client b/ssl/create_client
@@ -0,0 +1,5 @@
+#/bin/sh
+mkdir -p client/private
+chmod 700 client/private
+openssl genrsa -out client/private/client.key 1024
+openssl req -new -key client/private/client.key -out client/client.csr
diff --git a/ssl/create_server b/ssl/create_server
@@ -0,0 +1,5 @@
+#/bin/sh
+mkdir -p server/private
+chmod 700 server/private
+openssl genrsa -out server/private/server.key 1024
+openssl req -new -key server/private/server.key -out server/server.csr
diff --git a/ssl/sign_client b/ssl/sign_client
@@ -0,0 +1,2 @@
+#/bin/sh
+openssl x509 -req -days 3650 -in client/client.csr -CA ./ca/ca.crt -CAkey ./ca/private/ca.key -CAcreateserial -out client/client.crt
diff --git a/ssl/sign_server b/ssl/sign_server
@@ -0,0 +1,2 @@
+#/bin/sh
+openssl x509 -req -days 3650 -in server/server.csr -CA ./ca/ca.crt -CAkey ./ca/private/ca.key -CAcreateserial -out server/server.crt