#include "sock_tcp.h"
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <err.h>
/*
* Our sock_stream_type.methods.read implementation
*/
static int sock_tcp_read (struct sock_stream *base_sock, void *buf, size_t len)
{
struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
return read(sock->fd, buf, len);
}
/*
* Our sock_stream_type.methods.write implementation
*/
static int sock_tcp_write (struct sock_stream *base_sock, const void *buf, size_t len)
{
struct sock_tcp *sock = SOCK_FROM_BASE(base_sock, struct sock_tcp);
return write(sock->fd, buf, len);
}
/*
* Our sock_stream_type
*
* XXX: move to sock_tcp.h
*/
struct sock_stream_type sock_tcp_type = {
.methods.read = &sock_tcp_read,
.methods.write = &sock_tcp_write,
};
struct sock_tcp* sock_tcp_alloc (void)
{
struct sock_tcp *sock;
// alloc
if ((sock = calloc(1, sizeof(*sock))) == NULL)
errx(1, "calloc");
// initialize base
sock->base.type = &sock_tcp_type;
// done
return sock;
}
int sock_tcp_init_fd (struct sock_tcp *sock, int fd)
{
// initialize
sock->fd = fd;
// done
return 0;
}
int sock_tcp_init_connect (struct sock_tcp *sock, const char *hostname, const char *service)
{
struct addrinfo hints, *res, *r;
int _err;
// hints
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
// resolve
if ((_err = getaddrinfo(hostname, service, &hints, &res)))
errx(1, "getaddrinfo: %s", gai_strerror(_err));
// use
for (r = res; r; r = r->ai_next) {
// XXX: wrong
if ((sock->fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol)) < 0)
err(1, "socket");
if (connect(sock->fd, r->ai_addr, r->ai_addrlen))
err(1, "connect");
break;
}
// ensure we got some valid socket
if (sock->fd < 0)
errx(1, "no valid socket");
// ok, done
return 0;
}
// XXX: error handling
struct sock_stream* sock_tcp_connect (const char *host, const char *service)
{
struct sock_tcp *sock;
// allocate
sock = sock_tcp_alloc();
// connect
sock_tcp_init_connect(sock, host, service);
// done
return SOCK_TCP_BASE(sock);
}