# -*- coding: utf-8 -*-
# Elisa - Home multimedia server
# Copyright (C) 2006-2008 Fluendo Embedded S.L. (www.fluendo.com).
# All rights reserved.
#
# This file is available under one of two license agreements.
#
# This file is licensed under the GPL version 3.
# See "LICENSE.GPL" in the root of this distribution including a special
# exception to use Elisa with Fluendo's plugins.
#
# The GPL part of Elisa is also available under a commercial licensing
# agreement from Fluendo.
# See "LICENSE.Elisa" in the root directory of this distribution package
# for details on that license.

"""
Functions to retrieve hostname and IP address of the machine running Elisa
"""

__maintainer__ = 'Philippe Normand <philippe@fluendo.com>'

import socket
import struct
import sys
import platform

def _get_host_address_win():
    """
    Retrieve host address for Win32 platform

    @rtype: string
    """
    s = socket.gethostname()
    return socket.gethostbyname(s)

def _get_host_address_linux():
    """
    Retrieve host address for Linux platform

    @rtype: string
    """
    route_file = '/proc/net/route'
    route = open(route_file)
    host_address = '127.0.0.1'
    if route:
        tmp = route.readline() #skip first line
        while tmp != '':
            tmp = route.readline()
            l = tmp.split('\t')
            if len(l) > 2:
                if l[2] != '00000000': #default gateway...
                    host_address = get_ip_address(l[0])
                    break

    route.close()
    return host_address

def get_host_address():
    """
    Retrieve current host address for Win32 and Linux platforms

    @raises ValueError: if current system's platform is not windows or linux
    @rtype:             string
    """
    platform_type = platform.system().lower()
    if platform_type == "windows":
        return _get_host_address_win()
    elif platform_type == "linux":
        return _get_host_address_linux()
    else:
        raise ValueError("Unsupported platform")
    
def _get_linux_ip_address(ifname):
    """
    Retrieve IP address of the given network interface, on a Linux platform
    
    @param ifname: network interface name
    @type ifname:  string
    @rtype:        string
    """
    import fcntl
    
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    ip_address = socket.inet_ntoa(fcntl.ioctl(
        s.fileno(),
        0x8915,  # SIOCGIFADDR
        struct.pack('256s', ifname[:15])
        )[20:24])
    return ip_address

def _get_win32_ipaddress(ifname):
    """
    Retrieve IP address of the given network interface, on a Windows platform
    
    @param ifname: network interface name
    @type ifname:  string
    @rtype:        string
    """
    # TODO: implement me
    return ""

def _get_win32_default_iface():
    """
    Retrieve name of the network interface connected to the default
    gateway, on a Windows platform.

    @rtype: string
    """
    # TODO: implement me
    return "eth0"

def _get_linux_default_iface():
    """
    Retrieve name of the network interface connected to the default
    gateway, on a Linux platform.

    @rtype: string
    """
    route_file = '/proc/net/route'
    route = open(route_file)
    iface = 'eth0'
    if route:
        tmp = route.readline() #skip first line
        while tmp != '':
            tmp = route.readline()
            l = tmp.split('\t')
            if len(l) > 2:
                if l[2] == '00000000': #default gateway...
                    iface = l[0]
                    break
    route.close()
    return iface
    

def get_ip_address(ifname=None):
    """
    Retrieve IP address of the given network interface, on a Windows platform
    
    @raises ValueError: if current system's platform is not windows or linux
    @param ifname:      network interface name
    @type ifname:       string
    @rtype:             string
    """
    platform_type = platform.system().lower()
    if platform_type == "windows":
        if ifname is None:
            ifname = _get_win32_default_iface()
        return _get_win32_ip_address(ifname)
    elif platform_type == "linux":
        if ifname is None:
            ifname = _get_linux_default_iface()
        return _get_linux_ip_address(ifname)
    else:
        raise ValueError("Unsupported platform")
    
