/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ServerSocket.h"
#include "SocketError.h"

#ifdef HAVE_WINSOCK2_H
    #include <Winsock2.h>
    #include <Ws2tcpip.h> 
    #include <sys/stat.h>
    #define stat _stat
#else
    #include <unistd.h>
    #include <netdb.h>
    #include <fcntl.h>
    #include <sys/file.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <sys/types.h>
#include <assert.h>
#include <string>

using namespace activemq::network;

#ifdef HAVE_WINSOCK2_H

    // Static socket initializer needed for winsock

    ServerSocket::StaticServerSocketInitializer::StaticServerSocketInitializer () {
        socketInitError = NULL;
        const WORD version_needed = MAKEWORD(2,2); // lo-order byte: major version
        WSAData temp;
        if( WSAStartup(version_needed, &temp )){
           clear();
               socketInitError = new SocketException ( __FILE__, __LINE__,
                   "winsock.dll was not found");
        }
    }
    ServerSocket::StaticServerSocketInitializer::~StaticServerSocketInitializer () {
        clear();
        WSACleanup();
    }
   
    // Create static instance of the socket initializer.
    ServerSocket::StaticServerSocketInitializer 
        ServerSocket::staticSocketInitializer;
   
#endif


////////////////////////////////////////////////////////////////////////////////
ServerSocket::ServerSocket()
{
    socketHandle = Socket::INVALID_SOCKET_HANDLE;
   
#if defined(HAVE_WINSOCK2_H)
    if( ServerSocket::staticSocketInitializer.getSocketInitError() != NULL ) {
        throw *ServerSocket::staticSocketInitializer.getSocketInitError();
    }
#endif
}

////////////////////////////////////////////////////////////////////////////////
ServerSocket::~ServerSocket()
{
    // No shutdown, just close - dont want blocking destructor.
    close();
}

////////////////////////////////////////////////////////////////////////////////
void ServerSocket::bind( const char* host, int port ) throw ( SocketException )
{
    bind (host, port, SOMAXCONN);
}

////////////////////////////////////////////////////////////////////////////////
void ServerSocket::bind( const char* host, 
                         int port, 
                         int backlog ) throw ( SocketException )
{
    if(isBound()) {
        throw SocketException ( __FILE__, __LINE__, 
            "ServerSocket::bind - Socket already bound" );
    }
    
    // Create the socket.
    socketHandle = ::socket(AF_INET, SOCK_STREAM, 0 );
    if( socketHandle < 0) {
        socketHandle = Socket::INVALID_SOCKET_HANDLE;
            throw SocketException( __FILE__, __LINE__, SocketError::getErrorString().c_str());
    }
   
    // Verify the port value.
    if( port <= 0 || port > 65535 ) {
        throw SocketException( __FILE__, __LINE__, 
            "ServerSocket::bind - Port out of range: %d", port );
    }
      
    sockaddr_in bind_addr;
    bind_addr.sin_family = AF_INET;
    bind_addr.sin_port = htons((short)port);
    bind_addr.sin_addr.s_addr = 0; // To be set later down...
    memset(&bind_addr.sin_zero, 0, sizeof(bind_addr.sin_zero));
	int status;
	
    // Resolve name
#if defined(HAVE_STRUCT_ADDRINFO)    
    ::addrinfo hints;
    memset(&hints, 0, sizeof(addrinfo));
    hints.ai_family = PF_INET;
    struct addrinfo *res_ptr = NULL;
    status = ::getaddrinfo(host, NULL, &hints, &res_ptr);
    if( status != 0 || res_ptr == NULL) {
        throw SocketException( __FILE__, __LINE__, SocketError::getErrorString().c_str() );
    }
    assert(res_ptr->ai_addr->sa_family == AF_INET);
    // Porting: On both 32bit and 64 bit systems that we compile to soo far, sin_addr is a 32 bit value, not an unsigned long.
    assert(sizeof(((sockaddr_in*)res_ptr->ai_addr)->sin_addr.s_addr) == 4);
    bind_addr.sin_addr.s_addr = ((sockaddr_in*)res_ptr->ai_addr)->sin_addr.s_addr;
    freeaddrinfo(res_ptr);
#else
	struct ::hostent *he = ::gethostbyname(host);
	if( he == NULL ) {
        throw SocketException( __FILE__, __LINE__, "Failed to resolve hostname" );
	}
	bind_addr.sin_addr.s_addr = *((in_addr_t *)he->h_addr);
#endif


    // Set the socket to reuse the address.
    int value = 1;
    ::setsockopt(socketHandle, SOL_SOCKET, SO_REUSEADDR, (char*)&value, sizeof(int) );
      
    status = ::bind(socketHandle,
             reinterpret_cast<sockaddr*>(&bind_addr), sizeof( bind_addr ));

    if( status < 0 ){
        close();
        throw SocketException ( __FILE__, __LINE__, 
            "ServerSocket::bind - %s", SocketError::getErrorString().c_str() );
    }
    status = ::listen( socketHandle, (int)backlog );
    if( status < 0 ) {
        close();
        throw SocketException( __FILE__, __LINE__, SocketError::getErrorString().c_str() );
    }
}

////////////////////////////////////////////////////////////////////////////////
void ServerSocket::close() throw (cms::CMSException){
   
    if( isBound() ) {
        
        #if !defined(HAVE_WINSOCK2_H)
            ::close( socketHandle );
        #else
            ::closesocket( socketHandle );
        #endif

        socketHandle = Socket::INVALID_SOCKET_HANDLE;
    }
}

////////////////////////////////////////////////////////////////////////////////
bool ServerSocket::isBound() const {
    return this->socketHandle != Socket::INVALID_SOCKET_HANDLE;
}

////////////////////////////////////////////////////////////////////////////////
Socket* ServerSocket::accept() throw (SocketException)
{
    struct sockaddr_in temp;

    #if !defined(HAVE_WINSOCK2_H)
        socklen_t temp_len = sizeof( sockaddr_in );
    #else
        int temp_len = sizeof( sockaddr_in );
    #endif

    SocketHandle ss_socket_handle = (SocketHandle)0;
    
    // Loop to ignore any signal interruptions that occur during the operation.  
    do {
        
        ss_socket_handle = ::accept( socketHandle, 
                                     reinterpret_cast<struct sockaddr*>(&temp), 
                                     &temp_len );
        
    } while( ss_socket_handle < 0 && 
             SocketError::getErrorCode() == SocketError::INTERRUPTED );
        
    if( ss_socket_handle < 0 ) {
        throw SocketException( __FILE__, __LINE__, 
            "ServerSocket::accept- %s", SocketError::getErrorString().c_str() );
    }
    
    return new TcpSocket( ss_socket_handle );
}

