/*
 *   MediaMVP Server Library
 *
 *   (C) 2003 Dominic Morris
 *
 *   $Id: net.c,v 1.4 2004/03/20 11:18:21 dom Exp $
 *   $Date: 2004/03/20 11:18:21 $
 *
 *
 *   Some handy network utilities
 */


#include "libmvp_internal.h"

int  tcp_accept(int fd, char **hostbuf)
{
    struct sockaddr_in   addr;
    int                  addrlen;
    int                  cfd;

    addrlen = sizeof(struct sockaddr_in);

    cfd = accept(fd, (struct sockaddr *)&addr, (socklen_t*)&addrlen);

    if ( cfd == -1 ) {
        return -1;
    }

    /* We don't use threads, so this should be safe */
    *hostbuf = inet_ntoa(addr.sin_addr);

    return cfd;
}

int32_t host_resolve(char *serv)
{
    struct hostent     *he;
    he = gethostbyname(serv);

    if ( he == NULL ) {
        int32_t     addr;

        addr = inet_addr(serv);

        if ( addr == -1 ) {
            return -1;
        }

        he = gethostbyaddr(&addr,sizeof(addr),AF_INET);

        if ( he == NULL ) {
            return -1;
        }
    }

    return *(uint32_t *)he->h_addr;

}

int tcp_connect(char *serv, int port)
{
    int       fd;
    struct hostent     *he;
    struct sockaddr_in  sin;

    he = gethostbyname(serv);

    if ( he == NULL ) {
        int32_t     addr;

        addr = inet_addr(serv);

        if ( addr == -1 ) {
            return -1;
        }

        he = gethostbyaddr(&addr,sizeof(addr),AF_INET);

        if ( he == NULL ) {
            return -1;
        }
    }

    if ( ( fd = socket(AF_INET,SOCK_STREAM,0) ) == -1 ) {
        return -1;
    }

    memset(&sin,0,sizeof(sin));

    memcpy(&sin.sin_addr,he->h_addr,he->h_length);

    sin.sin_family = AF_INET;

    sin.sin_port = htons(port);

    if ( connect(fd,(struct sockaddr *)&sin, sizeof(sin)) == - 1 ) {
        close(fd);
        return -1;
    }

    return fd;
}


int tcp_listen(struct in_addr *addr, int port, int backlog)
{
    int     fd;
    int     len = 1;
    struct sockaddr_in saddr;

    if ( (fd = socket(AF_INET,SOCK_STREAM,0) ) == -1 ) {
        return -1;
    }

    setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(void *)&len,sizeof(len));

    memset(&saddr,0,sizeof(saddr));

    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);

    if ( addr == NULL ) {
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    } else {
        saddr.sin_addr = *addr;
    }

    if ( bind(fd,(struct sockaddr *)&saddr,sizeof(saddr)) == -1 ) {
        close(fd);
        return -1;
    }

    if ( listen(fd,backlog) == -1 ) {
        close(fd);
        return -1;
    }

    return fd;
}



int udp_listen(const char *iface, int port)
{
    int                 sock;
    struct sockaddr_in  serv_addr;
    int                 trueval = 1;


    memset((char *)&serv_addr, 0, sizeof(serv_addr));

    if (iface == NULL) {
        serv_addr.sin_addr.s_addr = INADDR_ANY;
    } else if (inet_aton(iface, &serv_addr.sin_addr) == 0) {
        return -1;
    }


    sock = socket(AF_INET, SOCK_DGRAM, 0);

    if (sock == -1) {
        return -1;
    }


    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&trueval, sizeof(trueval) ) == -1 ) {
        close(sock);
        return -1;
    }


    serv_addr.sin_port = htons((u_short)port);
    serv_addr.sin_family = AF_INET;

    if (bind(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1 ) {
        close(sock);
        return -1;
    }

    return sock;

}




int udp_send(char *data, int len, const char *addr, int port)
{
    int                 n;
    int                 sock;
    struct sockaddr_in  serv_addr;
    struct sockaddr_in  cli_addr;

    memset((char *)&cli_addr, 0, sizeof(cli_addr));
    memset((char *)&serv_addr, 0, sizeof(serv_addr));

    if (inet_aton(addr, &serv_addr.sin_addr) == 0) {
        return -1;
    }

    sock = socket(AF_INET, SOCK_DGRAM, 0);

    if (sock == - 1) {
        return -1;
    }
    cli_addr.sin_family = AF_INET;
    cli_addr.sin_port = htons((u_short)1234);
    cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    bind(sock,(struct sockaddr *)&cli_addr,sizeof(cli_addr));


    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons((u_short)port);

    n = sendto(sock, data, len, 0, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

    close(sock);

    return n;

}

/*
 * Local Variables:
 *  indent-tabs-mode:nil
 *  require-final-newline:t
 *  c-basic-offset: 4
 * End:
 */
