/**
 * @file interface.c
 *
 * @brief Service Placement interface implementation for Win32.
 *
 * Copyright 2007-2008, Freie Universitaet Berlin. All rights reserved.
 * Please refer to the COPYING file for detailed licensing information.
 *
 * @author Georg Wittenburg
 *
 * $Id: interface.c 2548 2008-02-13 19:20:58Z wittenbu $
 */



#include <stdio.h>
#include <stdlib.h>

#include <winsock2.h>
#include <windows.h>

#include "../../types.h"
#include "../../vars.h"
#include "../../interface.h"
#include "../../util/debug.h"
#include "../../util/net.h"



/**
 * @brief Win32 specific implemenation of __C_vprintf().
 */
void __C_vprintf(const char *format, va_list ap) {
	vprintf(format, ap);
}

/**
 * @brief Win32 specific implemenation of __C_random().
 */
double __C_random(double max) {
	return (max * ((double) rand() / (double) RAND_MAX));
}

/**
 * @brief Win32 specific implemenation of __C_time().
 */
C_time_t __C_time() {
	SYSTEMTIME system_time;
	FILETIME file_time;
	ULARGE_INTEGER time;	// Number of 100-nanosecond intervals since January 1, 1601 (UTC).
	GetLocalTime(&system_time);
	SystemTimeToFileTime(&system_time, &file_time);
	time.HighPart = file_time.dwHighDateTime;
	time.LowPart = file_time.dwLowDateTime;

	return (((C_time_t) time.QuadPart) / 10000000);
}

/**
 * @brief Win32 specific implemenation of __C_send().
 */
void __C_send(const packet_header_t* header, const void* payload) {
	int packet_size = sizeof(packet_header_t) + header->payload_length;
	char* buffer = NULL;
	struct sockaddr_in addr;

	C_DEBUG(C_DEBUG_LEVEL_VERBOSE, "Sending packet of %d byte(s) to node %s (seqno=%d)...\n", packet_size, addr_to_str(header->to), header->seqno);

	// Copy packet header and payload to buffer.
	MALLOC_ARRAY(buffer, char, packet_size);
	memcpy(buffer, header, sizeof(packet_header_t));
	if(header->payload_length > 0)
		memcpy(buffer + sizeof(packet_header_t), payload, header->payload_length);

	// Assemable address information.
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = header->to;
	addr.sin_port = htons(C_DEFAULT_UDP_PORT);

	// Send packet.
	if(sendto(C_udp_socket, buffer, packet_size, 0, (struct sockaddr*) &addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) {
		int errsv = WSAGetLastError();
		C_DEBUG(C_DEBUG_LEVEL_FATAL, "Sending packet failed (%d).\n", errsv);
		abort();
	}
}

/**
 * @brief Win32 specific implemenation of C_active_callback().
 *
 * Callback activation is handled in the main loop, hence there is nothing to
 * do.
 */
void __C_activate_callback(C_time_t time) {
	// Nothing to do on Win32.
}
