// Simple UDP listening server
//
// Author: Brian Lee
//
// Copyright: GPL V2
// See http://www.gnu.org/licenses/gpl.html

#include "EtherCard.h"
#include "net.h"

#define gPB ether.buffer

#define UDPSERVER_MAXLISTENERS 8	//the maximum number of port listeners.

typedef struct {
	UdpServerCallback callback;
	uint16_t port;
	bool listening;
} UdpServerListener;

UdpServerListener listeners[UDPSERVER_MAXLISTENERS];
byte numListeners = 0;

void EtherCard::udpServerListenOnPort(UdpServerCallback callback, uint16_t port) {
	if(numListeners < UDPSERVER_MAXLISTENERS)
	{
		listeners[numListeners] = (UdpServerListener){callback, port, true};
		numListeners++;
	}
}

void EtherCard::udpServerPauseListenOnPort(uint16_t port) {
	for(int i = 0; i < numListeners; i++)
	{
		if(gPB[UDP_DST_PORT_H_P] == (listeners[i].port >> 8) && gPB[UDP_DST_PORT_L_P] == ((byte) listeners[i].port)) {
			listeners[i].listening = false;
		}
	}
}

void EtherCard::udpServerResumeListenOnPort(uint16_t port) {
	for(int i = 0; i < numListeners; i++)
	{
		if(gPB[UDP_DST_PORT_H_P] == (listeners[i].port >> 8) && gPB[UDP_DST_PORT_L_P] == ((byte) listeners[i].port)) {
			listeners[i].listening = true;
		}
	}
}

bool EtherCard::udpServerListening() {
	return numListeners > 0;
}

bool EtherCard::udpServerHasProcessedPacket(word plen) {
	bool packetProcessed = false;
	for(int i = 0; i < numListeners; i++)
	{
		if(gPB[UDP_DST_PORT_H_P] == (listeners[i].port >> 8) && gPB[UDP_DST_PORT_L_P] == ((byte) listeners[i].port) && listeners[i].listening)
		{
			uint16_t datalen = (uint16_t) (gPB[UDP_LEN_H_P] << 8)  + gPB[UDP_LEN_L_P] - UDP_HEADER_LEN;
			listeners[i].callback(
				listeners[i].port,
				gPB + IP_SRC_P,
				(const char *) (gPB + UDP_DATA_P),
				datalen);
			packetProcessed = true;
		}
	}
	return packetProcessed;
}
