Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -12,12 +12,13 @@ map.c \ object.c \ range.c \ refpool.c \ stream.c \ - string.c + string.c \ + tcpsocket.c INCLUDES = ${SRCS:.c=.h} \ corefw.h \ hash.h include ../buildsys.mk Index: src/corefw.h ================================================================== --- src/corefw.h +++ src/corefw.h @@ -13,7 +13,8 @@ #include "map.h" #include "range.h" #include "refpool.h" #include "stream.h" #include "string.h" +#include "tcpsocket.h" #endif Index: src/file.c ================================================================== --- src/file.c +++ src/file.c @@ -22,11 +22,10 @@ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include @@ -127,11 +126,11 @@ CFWFile *file = ptr; close(file->fd); } -struct cfw_stream_ops stream_ops = { +static struct cfw_stream_ops stream_ops = { .read = file_read, .write = file_write, .eof = file_eof, .close = file_close }; Index: src/stream.c ================================================================== --- src/stream.c +++ src/stream.c @@ -44,15 +44,19 @@ ssize_t cfw_stream_read(void *ptr, void *buf, size_t len) { CFWStream *stream = ptr; + ssize_t ret; if (stream == NULL || stream->ops == NULL) return -1; - return stream->ops->read(stream, buf, len); + if ((ret = stream->ops->read(stream, buf, len)) < -1) + ret = -1; + + return ret; } bool cfw_stream_write(void *ptr, const void *buf, size_t len) { ADDED src/tcpsocket.c Index: src/tcpsocket.c ================================================================== --- src/tcpsocket.c +++ src/tcpsocket.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2012, Jonathan Schleifer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include + +#include +#include +#include + +#include "stream.h" +#include "tcpsocket.h" + +struct CFWTCPSocket { + CFWStream stream; + int fd; + bool eof; +}; + +static ssize_t +sock_read(void *ptr, void *buf, size_t len) +{ + CFWTCPSocket *sock = ptr; + ssize_t ret; + + if ((ret = recv(sock->fd, buf, len, 0)) == 0) + sock->eof = true; + + return ret; +} + +static bool +sock_write(void *ptr, const void *buf, size_t len) +{ + CFWTCPSocket *sock = ptr; + ssize_t ret; + + if ((ret = send(sock->fd, buf, len, 0)) < len) + return false; + + return true; +} + +static bool +sock_eof(void *ptr) +{ + CFWTCPSocket *sock = ptr; + + return sock->eof; +} + +static void +sock_close(void *ptr) +{ + CFWTCPSocket *sock = ptr; + + if (sock->fd != -1) + close(sock->fd); +} + +static struct cfw_stream_ops stream_ops = { + .read = sock_read, + .write = sock_write, + .eof = sock_eof, + .close = sock_close +}; + +static bool +ctor(void *ptr, va_list args) +{ + CFWTCPSocket *sock = ptr; + + sock->fd = -1; + sock->stream.ops = &stream_ops; + sock->eof = false; + + return true; +} + +static void +dtor(void *ptr) +{ + cfw_stream_close(ptr); +} + +bool +cfw_tcpsocket_connect(CFWTCPSocket *sock, const char *host, uint16_t port) +{ + struct addrinfo hints, *res, *res0; + char portstr[7]; + + if (sock->fd != -1) + return false; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + snprintf(portstr, 7, "%" PRIu16, port); + + if (getaddrinfo(host, portstr, &hints, &res0)) + return false; + + for (res = res0; res != NULL; res = res->ai_next) { + if ((sock->fd = socket(res->ai_family, res->ai_socktype, + res->ai_protocol)) == -1) + continue; + + if (connect(sock->fd, res->ai_addr, res->ai_addrlen) == -1) { + close(sock->fd); + sock->fd = -1; + continue; + } + + break; + } + + freeaddrinfo(res0); + + return (sock->fd != -1); +} + +static CFWClass class = { + .name = "CFWTCPSocket", + .size = sizeof(CFWTCPSocket), + .ctor = ctor, + .dtor = dtor +}; +CFWClass *cfw_tcpsocket = &class; ADDED src/tcpsocket.h Index: src/tcpsocket.h ================================================================== --- src/tcpsocket.h +++ src/tcpsocket.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2012, Jonathan Schleifer + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __COREFW_TCPSOCKET_H__ +#define __COREFW_TCPSOCKET_H__ + +typedef struct CFWTCPSocket CFWTCPSocket; + +extern CFWClass *cfw_tcpsocket; +extern bool cfw_tcpsocket_connect(CFWTCPSocket*, const char*, uint16_t); + +#endif