socket.c 3.28 KB
#include <stdio.h>      /* for printf() and fprintf() */
#include <sys/types.h>  /* SO_REUSEADDR */
#include <sys/socket.h> /* for socket(), bind(), and connect() */
#include <arpa/inet.h>  /* for sockaddr_in and inet_ntoa() */
#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <unistd.h>     /* for close() */
#include <errno.h>      /* for errno */
#include <stdarg.h>

#include "logger.h"
#include "cclass.h"
#include "socket.h"


INIT_CLASS(SOCK);

__construct(SOCK)
{
	this->logger = va_arg(* params, struct _logger *);
	this->port   = va_arg(* params, int);
}

__destruct(SOCK)
{
	if (0 != this->handle) {
		shutdown(this->handle, SHUT_RDWR);
		close(this->handle);
	}
}

__jsonConst(SOCK) {}
__toJson(SOCK) {}
__clear(SOCK) {}


void
sock_initServer(SOCK this, int backlog)
{
    struct sockaddr_in addr;       /* Local address */
    int                reUse = 1;  /* TODO: make this configurable */

    /* Create socket for incoming connections */
    if (-1 == (this->handle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
        logger_log(this->logger, LOGGER_CRIT,
                "error opening socket: %s - service terminated",
                strerror(errno));
        exit(EXIT_FAILURE);
    }

    /* Make the socket REUSE a TIME_WAT socket */
    setsockopt(this->handle, SOL_SOCKET, SO_REUSEADDR, &reUse, sizeof (reUse));

    /* Construct local address structure */
    memset(&addr, 0, sizeof(addr));       /* Zero out structure */

    addr.sin_family      = AF_INET;           /* Internet address family */
    addr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
    addr.sin_port        = htons(this->port); /* Local port */

    /* Bind to the local address */
    if (-1 == bind(this->handle, (struct sockaddr *) &addr, sizeof(addr))) {
        logger_log(this->logger, LOGGER_CRIT,
                "error binding socket: %s - service terminated",
                strerror(errno));
        exit(EXIT_FAILURE);
    }

    /* Mark the socket so it will listen for incoming connections */
    if (-1 == listen(this->handle, backlog)) {
        logger_log(this->logger, LOGGER_CRIT,
                "error binding socket: %s - service terminated",
                strerror(errno));
        exit(EXIT_FAILURE);
    }
}

SOCK
sock_accept(SOCK this, char remoteAddr[16])
{
    SOCK               sock;   /* Socket for client */
    struct sockaddr_in addr;   /* Client address */
    unsigned int       len;    /* Length of client address data structure */

    /* Set the size of the in-out parameter */
    len = sizeof(addr);

	sock = new(SOCK, this->logger, this->port);
	/**
	 * @TODO: change port to remote port on success
	 */

    /* Wait for a client to connect */
    if (-1 == (sock->handle = accept(this->handle, (struct sockaddr *) &addr, &len))) {
        logger_log(this->logger, LOGGER_WARNING,
                "error acception connection: %s", strerror(errno));
    } else {
        strncpy (remoteAddr, inet_ntoa(addr.sin_addr), sizeof(remoteAddr)-1);
    }

    /* clntSock is connected to a client! */
	/**
	 * @TODO add verbosity level to logger
	 */
//    if (0 != this->logger->verbose) {
        logger_log(this->logger, LOGGER_INFO,
				"handling client %s\n", inet_ntoa(addr.sin_addr));
//    }

    return sock;
}

// vim: set ts=4 sw=4: