/* Copyright 2013 Akira Ohta (akohta001@gmail.com)
    This file is part of ntch.

    The ntch is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    The ntch is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ntch.  If not, see <http://www.gnu.org/licenses/>.
    
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iconv.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

#include "utils/nt_std_t.h"
#include "net/nt_socket.h"

void nt_socket_free(nt_socket_tp socketp)
{
	free(socketp);
}

nt_socket_tp nt_socket_init(int port, char *addr)
{
	struct hostent *hostinfo;

	nt_socket_tp ptr = malloc(sizeof(nt_socket_t));
	if(ptr == NULL)
		return NULL;
		
	ptr->h_mutex = nt_mutex_get_one_time_handle(NT_MUTEX_ROOT_NAME_NET);
	if(!ptr->h_mutex){
		free(ptr);
		return NULL;
	}
	if(!nt_mutex_add_mbs_moniker(ptr->h_mutex, addr)){
		free(ptr);
		return NULL;
	}
	
	ptr->_sockaddr_in.sin_family = AF_INET;
	ptr->_sockaddr_in.sin_port = htons(port);
	ptr->_sockaddr_in.sin_addr.s_addr = inet_addr(addr);
	if(ptr->_sockaddr_in.sin_addr.s_addr == 0xffffffff){
		hostinfo = gethostbyname(addr);
		if(NULL == hostinfo)
			return NULL;
		if(hostinfo->h_addrtype != AF_INET)
			return NULL;
		if(hostinfo->h_addr_list[0] == NULL)
			return NULL;
		memcpy(&ptr->_sockaddr_in.sin_addr.s_addr, 
				hostinfo->h_addr_list[0], 4);
	}
	return ptr;
}

int nt_socket_connect(nt_socket_tp socketp, char* data, int data_len)
{
	int sockfd;
	int len;
	int result;

	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd == -1)
		return -1;
	len = sizeof(socketp->_sockaddr_in);
	
	nt_mutex_lock(socketp->h_mutex);
	result = connect(sockfd, 
			(struct sockaddr *)&(socketp->_sockaddr_in), len);
	nt_mutex_unlock(socketp->h_mutex);
	if(result == -1){
		close(sockfd);
		return -1;
	}

	result = write(sockfd, data, data_len);
	if(result == -1){
		close(sockfd);
		return -1;
	}
	return sockfd;
}
