/*
 * Soubor:  oscar.c
 * Datum:   06.08.2012
 * Autor:   Stanislav Bárta, xbarta29@stud.fit.vutbr.cz
 * Projekt: IM modul
 * Popis:   soubor obsahujici funkce pro zpracovani protokolu OSCAR
 */

#include "oscar.h"

enum STAV
{
	NEPRIPOJEN,
	POZADAVEK_NA_KLIC,
	KLIC_ZISKAN,
	AUTENTIZACE,
	AUTENTIZOVAN,

	PRIHLASENI_K_SERVERU,
	ZISKAN_SEZNAM_SLUZEB,
	POZADAVEK_NA_VERZE_SLUZEB,
	ZISKANI_VERZI_SLUZEB,
	POZADAVEK_NA_ZISKANI_LIMITU_PRIPOJENI,
	LIMITY_ZISKANY,
	LIMITY_POTVRZENY,
	ODESLAN_STATUS,
	PRIHLASEN,
	ZAHAJENA_SIFROVANA_KOMUNIKACE
};

// globalne ulozen aktualni stav pro lepsi pristup z pomocnych funkci.
int *aktualni_stav;

/*
 * zpracovani paketu protokolu OSCAR
 * zprava je rozdelena na FLAP ramce a ty jsou dale zpracovany
 */
void zpracuj_oscar(struct data_packetu *zprava, struct sezeni *Sezeni)
{
	aktualni_stav = &(Sezeni->aktualni_stav);

	char **potreba_dokoncit_prichozi = &(Sezeni->potreba_dokoncit_prichozi);
	int *ocekavat_dalsi_prichozi = &(Sezeni->ocekavat_dalsi_prichozi);

	char **potreba_dokoncit_odchozi = &(Sezeni->potreba_dokoncit_odchozi);
	int *ocekavat_dalsi_odchozi = &(Sezeni->ocekavat_dalsi_odchozi);

	int uvolnit = 0;
	char *pomocny_ukazatel;

	char *data = zprava->data;
	int zpracovano = 0; // obsahuj udaj o tom kolik jiz bylo zpracovano z aktualni zpravy
	int zpracuj_dalsi = 1;
	int dokonceno = 0; // obsahuje udaj kolik bylo ke zprave pridano dat ulozenych z minula

	if(((struct flap*) data)->id != 0x2a && !*ocekavat_dalsi_prichozi && !*ocekavat_dalsi_odchozi)
	{
		// prijali jsme neco co nezacina hodnotou 0x2a (zacatek FLAP) a pritom nemusime zpravu dokoncovat -> nejspis chyba
		return;
	}

	if(((struct flap*) data)->id == 0x2a && (*ocekavat_dalsi_prichozi || *ocekavat_dalsi_odchozi))
	{
		// prijali jsme zpravu zacinajici hodnotou 0x2a (zacatek FLAP) a pritom musime zpravu dokoncovat -> asi ztracen paket -> ulozene se zahodi
		if(*ocekavat_dalsi_prichozi && zprava->smer == prichozi)
		{
			*ocekavat_dalsi_prichozi = 0;
			free(*potreba_dokoncit_prichozi);
		}
		else if(*ocekavat_dalsi_odchozi && zprava->smer == odchozi)
		{
			*ocekavat_dalsi_odchozi = 0;
			free(*potreba_dokoncit_odchozi);
		}
	}

	if(*ocekavat_dalsi_prichozi && zprava->smer == prichozi)
	{
		kopie_retezce(data, &pomocny_ukazatel, zprava->velikost_dat);
		data = spoj_retezce(potreba_dokoncit_prichozi, *ocekavat_dalsi_prichozi, &pomocny_ukazatel, zprava->velikost_dat);
		dokonceno = *ocekavat_dalsi_prichozi;
		*ocekavat_dalsi_prichozi = 0;
		uvolnit = 1;
	}
	else if(*ocekavat_dalsi_odchozi && zprava->smer == odchozi)
	{
		kopie_retezce(data, &pomocny_ukazatel, zprava->velikost_dat);
		data = spoj_retezce(potreba_dokoncit_odchozi, *ocekavat_dalsi_odchozi, &pomocny_ukazatel, zprava->velikost_dat);
		dokonceno = *ocekavat_dalsi_odchozi;
		*ocekavat_dalsi_odchozi = 0;
		uvolnit = 1;
	}

	while(zpracuj_dalsi)
	{
		// nemame dostatek dat pro pretypovani na FLAP hlavicku
		if((zprava->velikost_dat + dokonceno) - zpracovano < FLAP_LENGTH)
		{
			if(zprava->smer == prichozi)
			{
				kopie_retezce(data + zpracovano, potreba_dokoncit_prichozi, (zprava->velikost_dat + dokonceno) - zpracovano);
				*ocekavat_dalsi_prichozi = (zprava->velikost_dat + dokonceno) - zpracovano;
			}
			else if(zprava->smer == odchozi)
			{
				kopie_retezce(data + zpracovano, potreba_dokoncit_odchozi, (zprava->velikost_dat + dokonceno) - zpracovano);
				*ocekavat_dalsi_odchozi = (zprava->velikost_dat + dokonceno) - zpracovano;
			}
			return;
		}

		struct flap *flap_ramec = (struct flap*) (data + zpracovano);

		// nemame cely flap ramec takze bude potreba pockat na dokonceni
		if(zpracovano + FLAP_LENGTH + ntohs(flap_ramec->data_size) > zprava->velikost_dat + dokonceno)
		{
			if(zprava->smer == prichozi)
			{
				kopie_retezce(data + zpracovano, potreba_dokoncit_prichozi, (zprava->velikost_dat + dokonceno) - zpracovano);
				*ocekavat_dalsi_prichozi = (zprava->velikost_dat + dokonceno) - zpracovano;
			}
			else if(zprava->smer == odchozi)
			{
				kopie_retezce(data + zpracovano, potreba_dokoncit_odchozi, (zprava->velikost_dat + dokonceno) - zpracovano);
				*ocekavat_dalsi_odchozi = (zprava->velikost_dat + dokonceno) - zpracovano;
			}

			return;
		}

		// identifikace kanalu protkolu FLAP a podle nej protokolu SNAC
		if(flap_ramec->channel == 1)
		{
			if(ntohs(flap_ramec->data_size) > 4) // velikost 4 znamena ze je obsazena pouze informace o verzi protokolu a ta nas nezajima
			{
				struct tlv *tlv_struktura = (struct tlv*) (data + FLAP_LENGTH + 4);

				if(ntohs(tlv_struktura->type) == 0x06)
				{
					*aktualni_stav = PRIHLASENI_K_SERVERU;
				}
			}
			
			if(zprava->smer == prichozi)
			{
				char *vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_PRIPOJENI_K_SERVERU, USPESNE, &(zprava->cas_zachyceni), NULL, NULL, NULL, NULL);
				odesli_iri(vytvorena_iri);
				free(vytvorena_iri);
			}
		}
		else if(flap_ramec->channel == 2)
		{
			struct snac *snac_zprava = (struct snac*) (data + zpracovano + FLAP_LENGTH);

			int group = ntohs(snac_zprava->group);
			if(group == 0x01)
			{
				group0x01(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x02)
			{
				group0x02(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x03)
			{
				group0x03(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x04)
			{
				group0x04(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x06)
			{
				group0x06(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x07)
			{
				group0x07(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x08)
			{
				group0x08(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x09)
			{
				group0x09(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x0a)
			{
				group0x0a(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x0b)
			{
				group0x0b(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x0d)
			{
				group0x0d(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x0e)
			{
				group0x0e(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x0f)
			{
				group0x0f(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x10)
			{
				group0x10(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x13)
			{
				group0x13(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x15)
			{
				group0x15(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
			else if(group == 0x17)
			{
				group0x17(snac_zprava, ntohs(flap_ramec->data_size), Sezeni, &(zprava->cas_zachyceni));
			}
		}
		else if(flap_ramec->channel == 3)
		{

		}
		else if(flap_ramec->channel == 4)
		{
			if(*aktualni_stav == PRIHLASEN)
			{
				char *vytvorena_iri;
				if(Sezeni->aktivni)
				{
					vytvorena_iri = vytvor_iri(IRI_END, OSCAR, Sezeni, TYP_ODHLASEN, USPESNE, &(zprava->cas_zachyceni), NULL, NULL, NULL, NULL);
				}
				else
				{
					vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_ODHLASEN, USPESNE, &(zprava->cas_zachyceni), NULL, NULL, NULL, NULL);
				}
				odesli_iri(vytvorena_iri);
				free(vytvorena_iri);
			}
			*aktualni_stav = NEPRIPOJEN;
			Sezeni->aktivni = 0;
			Sezeni->ukonceno = 1;
		}
		else if(flap_ramec->channel == 5)
		{

		}

		// zprava kterou zpracovavame jeste nebyla zpracovana cela
		if(zprava->velikost_dat + dokonceno > zpracovano + ntohs(flap_ramec->data_size)+FLAP_LENGTH)
		{
			zpracovano += ntohs(flap_ramec->data_size)+FLAP_LENGTH;
			// dojde k dalsimu pruchodu cyklem
		}
		else
		{
			zpracuj_dalsi = 0;
			// ukonceni cyklu
		}
	}

	if(uvolnit)
	{
		free(data);
	}
}

/*** dale nasleduji funkce pro zpracovani jednotlivych skupin zprav protokolu SNAC ***/

void group0x01(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{
		if(*aktualni_stav == ODESLAN_STATUS || *aktualni_stav == LIMITY_POTVRZENY)
		{
			*aktualni_stav = PRIHLASEN;
			if((Sezeni->ID_uzivatele != NULL) && !Sezeni->aktivni)
			{
				Sezeni->aktivni = 1;
				char *vytvorena_iri = vytvor_iri(IRI_BEGIN, OSCAR, Sezeni, TYP_PRIHLASEN, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
				odesli_iri(vytvorena_iri);
				free(vytvorena_iri);
			}
		}
	}
	else if(typ == 0x03)
	{
		if(*aktualni_stav == PRIHLASENI_K_SERVERU)
		{
			*aktualni_stav = ZISKAN_SEZNAM_SLUZEB;
		}
	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{
		if(*aktualni_stav == ZISKANI_VERZI_SLUZEB)
		{
			*aktualni_stav = POZADAVEK_NA_ZISKANI_LIMITU_PRIPOJENI;
		}
	}
	else if(typ == 0x07)
	{
		if(*aktualni_stav == POZADAVEK_NA_ZISKANI_LIMITU_PRIPOJENI)
		{
			*aktualni_stav = LIMITY_ZISKANY;
		}
	}
	else if(typ == 0x08)
	{
		if(*aktualni_stav == LIMITY_ZISKANY)
		{
			*aktualni_stav = LIMITY_POTVRZENY;
		}
	}
	else if(typ == 0x09)
	{

	}
	else if(typ == 0x0a)
	{

	}
	else if(typ == 0x0b)
	{

	}
	else if(typ == 0x0c)
	{

	}
	else if(typ == 0x0d)
	{

	}
	else if(typ == 0x0e)
	{

	}
	else if(typ == 0x0f)
	{
		if(Sezeni->ID_uzivatele == NULL)
		{
			int posun = 0;
			if(ntohs(snac_zprava->flags) == 0x8000)
			{
				// + 2 podle informaci v popisu flagu (ktere nejsou dostatecne zdokumentovany)
				struct tlv *aktualni_tlv = (struct tlv*) (((char *)snac_zprava) + SNAC_LENGTH + 2);
				posun = ntohs(aktualni_tlv->length) + 6;
			}

			char* pomocna_delka = NULL;
			kopie_retezce(((char *)snac_zprava) + SNAC_LENGTH + posun, &(pomocna_delka), 1); // znak reprezentujici delku uin
			int delka = (int)(pomocna_delka[0]);
			free(pomocna_delka);
			kopie_retezce(((char *)snac_zprava) + SNAC_LENGTH + posun + 1, &(Sezeni->ID_uzivatele), delka);
		}

		if(*aktualni_stav == PRIHLASEN)
		{
			if((Sezeni->ID_uzivatele != NULL) && !Sezeni->aktivni)
			{
				Sezeni->aktivni = 1;
				char *vytvorena_iri = vytvor_iri(IRI_BEGIN, OSCAR, Sezeni, TYP_PRIHLASEN, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
				odesli_iri(vytvorena_iri);
				free(vytvorena_iri);
			}
		}
	}
	else if(typ == 0x10)
	{

	}
	else if(typ == 0x11)
	{

	}
	else if(typ == 0x12)
	{

	}
	else if(typ == 0x13)
	{

	}
	else if(typ == 0x14)
	{

	}
	else if(typ == 0x15)
	{

	}
	else if(typ == 0x16)
	{

	}
	else if(typ == 0x17)
	{
		if(*aktualni_stav == ZISKAN_SEZNAM_SLUZEB)
		{
			*aktualni_stav = POZADAVEK_NA_VERZE_SLUZEB;
		}
	}
	else if(typ == 0x18)
	{
		if(*aktualni_stav == POZADAVEK_NA_VERZE_SLUZEB)
		{
			*aktualni_stav = ZISKANI_VERZI_SLUZEB;
		}
	}
	else if(typ == 0x1e)
	{
		if(*aktualni_stav == NEPRIPOJEN)
		{
			*aktualni_stav = PRIHLASEN;
		}
		
		if(*aktualni_stav == LIMITY_POTVRZENY)
		{
			*aktualni_stav = ODESLAN_STATUS;
		}
		else if(*aktualni_stav == ZISKANI_VERZI_SLUZEB)
		{
			*aktualni_stav = ODESLAN_STATUS;
		}
		else if(*aktualni_stav == PRIHLASEN)
		{
			int posun = 0;
			if(ntohs(snac_zprava->flags) == 0x8000)
			{
				// + 2 podle informaci v popisu flagu (ktere nejsou dostatecne zdokumentovany)
				struct tlv *aktualni_tlv = (struct tlv*) (((char *)snac_zprava) + SNAC_LENGTH + 2);
				posun = ntohs(aktualni_tlv->length) + 6;
			}
			//projdeme tlv
			int zpracovano = posun;
			while(zpracovano < velikost_dat - SNAC_LENGTH)
			{
				struct tlv *aktualni_tlv = (struct tlv*) (((char *)snac_zprava) + SNAC_LENGTH + zpracovano);

				if(ntohs(aktualni_tlv->type) == 0x06)
				{
					uint32_t status = ntohl((long)aktualni_tlv->value);
					status = status << 16;
					status = status >> 16;

					if(status == 0x0000)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_ONLINE, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_ONLINE, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x0001)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_AWAY, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_AWAY, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x0013) // drive 0x0002
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_DND, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_DND, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x0005) // drive 0x0004
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_NA, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_NA, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x0011) // drive 0x0010
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_OCCUPIED, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_OCCUPIED, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x0020)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_CHAT, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_CHAT, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x0100)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_INVISIBLE, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_INVISIBLE, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x3000)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_EVIL, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_EVIL, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x4000)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_DEPRESSION, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_DEPRESSION, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x5000)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_ATHOME, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_ATHOME, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x6000)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_ATWORK, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_ATWORK, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
					else if(status == 0x2001)
					{
						char *vytvorena_iri;
						if(Sezeni->aktivni)
						{
							vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_LUNCH, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						else
						{
							vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_LUNCH, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
						}
						odesli_iri(vytvorena_iri);
						free(vytvorena_iri);
					}
				}

				zpracovano += ntohs(aktualni_tlv->length);
				zpracovano += 4; // tlv hlavicka
			}
		}
	}
	else if(typ == 0x1f)
	{

	}
	else if(typ == 0x20)
	{

	}
	else if(typ == 0x21)
	{

	}
}

void group0x02(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{

	}
	else if(typ == 0x07)
	{

	}
	else if(typ == 0x08)
	{

	}
	else if(typ == 0x09)
	{

	}
	else if(typ == 0x0a)
	{

	}
	else if(typ == 0x0b)
	{

	}
	else if(typ == 0x0c)
	{

	}
	else if(typ == 0x0f)
	{

	}
	else if(typ == 0x10)
	{

	}
	else if(typ == 0x15)
	{

	}
}

void group0x03(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{

	}
	else if(typ == 0x07)
	{

	}
	else if(typ == 0x08)
	{

	}
	else if(typ == 0x09)
	{

	}
	else if(typ == 0x0a)
	{

	}
	else if(typ == 0x0b)
	{

	}
	else if(typ == 0x0c)
	{

	}
}

void group0x04(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{
		// urceni jestli jde o obycejnou textovou zpravu
		uint16_t *pomocny = (uint16_t *)(((char *)snac_zprava) + SNAC_LENGTH + 8);
		if(ntohs(*pomocny) != 0x1)
		{
			return;
		}

		char *pomocny_prijemce = NULL;
		char* pomocna_delka = NULL;
		//posun na uin (velikost podle informaci o formatu zpravy)
		int posun = 8 + 2;
		kopie_retezce(((char *)snac_zprava) + SNAC_LENGTH + posun, &(pomocna_delka), 1); // znak reprezentujici delku uin
		int delka = (int)(pomocna_delka[0]);
		free(pomocna_delka);
		kopie_retezce(((char *)snac_zprava) + SNAC_LENGTH + posun + 1, &pomocny_prijemce, delka);
		
		if(*aktualni_stav == NEPRIPOJEN)
		{
			*aktualni_stav = PRIHLASEN;
		}
		
		if(*aktualni_stav == PRIHLASEN)
		{
			char *vytvorena_iri;
			if(Sezeni->aktivni)
			{
				vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_ODESLANA_ZPRAVA, USPESNE, cas_zachyceni, NULL, NULL, pomocny_prijemce, NULL);
			}
			else
			{
				vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_ODESLANA_ZPRAVA, USPESNE, cas_zachyceni, NULL, NULL, pomocny_prijemce, NULL);
			}
			odesli_iri(vytvorena_iri);
			free(vytvorena_iri);
		}
		free(pomocny_prijemce);
	}
	else if(typ == 0x07)
	{
		// urceni jestli jde o obycejnou textovou zpravu
		uint16_t *pomocny = (uint16_t *)(((char *)snac_zprava) + SNAC_LENGTH + 8);
		if(ntohs(*pomocny) != 0x1)
		{
			return;
		}

		char *pomocny_odesilatel = NULL;
		char* pomocna_delka = NULL;
		//posun na uin (velikost podle informaci o formatu zpravy)
		int posun = 8 + 2;
		kopie_retezce(((char *)snac_zprava) + SNAC_LENGTH + posun, &(pomocna_delka), 1); // znak reprezentujici delku uin
		int delka = (int)(pomocna_delka[0]);
		free(pomocna_delka);
		kopie_retezce(((char *)snac_zprava) + SNAC_LENGTH + posun + 1, &pomocny_odesilatel, delka);
		
		if(*aktualni_stav == NEPRIPOJEN)
		{
			*aktualni_stav = PRIHLASEN;
		}
		
		if(*aktualni_stav == PRIHLASEN)
		{
			char *vytvorena_iri;
			if(Sezeni->aktivni)
			{
				vytvorena_iri = vytvor_iri(IRI_CONTINUE, OSCAR, Sezeni, TYP_PRIJATA_ZPRAVA, USPESNE, cas_zachyceni, NULL, pomocny_odesilatel, NULL, NULL);
			}
			else
			{
				vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_PRIJATA_ZPRAVA, USPESNE, cas_zachyceni, NULL, pomocny_odesilatel, NULL, NULL);
			}
			odesli_iri(vytvorena_iri);
			free(vytvorena_iri);
		}
		free(pomocny_odesilatel);
	}
	else if(typ == 0x08)
	{

	}
	else if(typ == 0x09)
	{

	}
	else if(typ == 0x0a)
	{

	}
	else if(typ == 0x0b)
	{

	}
	else if(typ == 0x0c)
	{

	}
	else if(typ == 0x14)
	{

	}
}


void group0x06(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
}

void group0x07(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{

	}
	else if(typ == 0x07)
	{

	}
	else if(typ == 0x08)
	{

	}
	else if(typ == 0x09)
	{

	}
}

void group0x08(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
}

void group0x09(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{

	}
	else if(typ == 0x07)
	{

	}
	else if(typ == 0x08)
	{

	}
	else if(typ == 0x09)
	{

	}
	else if(typ == 0x0a)
	{

	}
	else if(typ == 0x0b)
	{

	}
}

void group0x0a(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
}

void group0x0b(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
}


void group0x0d(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{

	}
	else if(typ == 0x07)
	{

	}
	else if(typ == 0x08)
	{

	}
	else if(typ == 0x09)
	{

	}
}

void group0x0e(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{

	}
	else if(typ == 0x07)
	{

	}
	else if(typ == 0x08)
	{

	}
	else if(typ == 0x09)
	{

	}
}

void group0x0f(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
}

void group0x10(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{

	}
	else if(typ == 0x07)
	{

	}
}

void group0x13(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{

	}
	else if(typ == 0x07)
	{

	}
	else if(typ == 0x08)
	{

	}
	else if(typ == 0x09)
	{

	}
	else if(typ == 0x0a)
	{

	}
	else if(typ == 0x0e)
	{

	}
	else if(typ == 0x0f)
	{

	}
	else if(typ == 0x11)
	{

	}
	else if(typ == 0x12)
	{

	}
	else if(typ == 0x14)
	{

	}
	else if(typ == 0x15)
	{

	}
	else if(typ == 0x16)
	{

	}
	else if(typ == 0x18)
	{

	}
	else if(typ == 0x19)
	{

	}
	else if(typ == 0x1a)
	{

	}
	else if(typ == 0x1b)
	{

	}
	else if(typ == 0x1c)
	{

	}
}

void group0x15(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{

	}
	else if(typ == 0x03)
	{

	}
}

void group0x17(struct snac *snac_zprava, int velikost_dat, struct sezeni *Sezeni, struct timeval *cas_zachyceni)
{
	int typ = ntohs(snac_zprava->type);

	if(typ == 0x01)
	{

	}
	else if(typ == 0x02)
	{
		if(*aktualni_stav == KLIC_ZISKAN)
		{
			*aktualni_stav = AUTENTIZACE;
		}
	}
	else if(typ == 0x03)
	{
		if(*aktualni_stav == AUTENTIZACE)
		{
			// pomocne promenne pro iformaci o pritomnosti jednotlivych tlv
			int _0x06 = 0, _0x08 = 0;

			int posun = 0;
			if(ntohs(snac_zprava->flags) == 0x8000)
			{
				// + 2 podle informaci v popisu flagu (ktere nejsou dostatecne zdokumentovany)
				struct tlv *aktualni_tlv = (struct tlv*) (((char *)snac_zprava) + SNAC_LENGTH + 2);
				posun = ntohs(aktualni_tlv->length) + 6;
			}

			//projdeme tlv
			int zpracovano = posun;
			while(zpracovano < velikost_dat - SNAC_LENGTH)
			{
				struct tlv *aktualni_tlv = (struct tlv*) (((char *)snac_zprava) + SNAC_LENGTH + zpracovano);

				if(ntohs(aktualni_tlv->type) == 0x01)
				{
					kopie_retezce(((char *)aktualni_tlv)+4, &(Sezeni->ID_uzivatele), ntohs(aktualni_tlv->length));
				}
				else if(ntohs(aktualni_tlv->type) == 0x06)
				{
					_0x06 = 1;
				}
				else if(ntohs(aktualni_tlv->type) == 0x08)
				{
					_0x08 = 1;
				}

				zpracovano += ntohs(aktualni_tlv->length);
				zpracovano += 4; // tlv hlavicka
			}

			if(_0x06)
			{
				char *vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_AUTENTIZACE, USPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
				odesli_iri(vytvorena_iri);
				free(vytvorena_iri);
				*aktualni_stav = AUTENTIZOVAN;
			}
			else if(_0x08)
			{
				char *vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_AUTENTIZACE, NEUSPESNE, cas_zachyceni, NULL, NULL, NULL, NULL);
				odesli_iri(vytvorena_iri);
				free(vytvorena_iri);
				*aktualni_stav = NEPRIPOJEN;
			}
		}
	}
	else if(typ == 0x04)
	{

	}
	else if(typ == 0x05)
	{

	}
	else if(typ == 0x06)
	{
		if(*aktualni_stav == NEPRIPOJEN)
		{
			int posun = 0;
			if(ntohs(snac_zprava->flags) == 0x8000)
			{
				// + 2 podle informaci v popisu flagu (ktere nejsou dostatecne zdokumentovany)
				struct tlv *aktualni_tlv = (struct tlv*) (((char *)snac_zprava) + SNAC_LENGTH + 2);
				posun = ntohs(aktualni_tlv->length) + 6;
			}
			//projdeme tlv
			int zpracovano = posun;
			while(zpracovano < velikost_dat - SNAC_LENGTH)
			{
				struct tlv *aktualni_tlv = (struct tlv*) (((char *)snac_zprava) + SNAC_LENGTH + zpracovano);

				if(ntohs(aktualni_tlv->type) == 0x01)
				{
					if(Sezeni->ID_uzivatele == NULL)
					{
						kopie_retezce(((char *)aktualni_tlv)+4, &(Sezeni->ID_uzivatele), ntohs(aktualni_tlv->length));
					}
				}

				zpracovano += ntohs(aktualni_tlv->length);
				zpracovano += 4; // tlv hlavicka
			}

			*aktualni_stav = POZADAVEK_NA_KLIC;
		}
	}
	else if(typ == 0x07)
	{
		if(*aktualni_stav == POZADAVEK_NA_KLIC)
		{
			*aktualni_stav = KLIC_ZISKAN;
		}
	}
	else if(typ == 0x0a)
	{

	}
	else if(typ == 0x0b)
	{

	}
}

/*
 * zjisti stav ukonceneho spojeni a v pripade potreby vytvori odpovidajici IRI zpravy
 */
void ukonci_oscar(struct data_packetu *zprava, struct sezeni *Sezeni)
{
	int *aktualni_stav = &(Sezeni->aktualni_stav);

	if(*aktualni_stav != NEPRIPOJEN)
	{
		char *vytvorena_iri;
		if(Sezeni->aktivni)
		{
			vytvorena_iri = vytvor_iri(IRI_END, OSCAR, Sezeni, TYP_ODHLASEN, USPESNE, &(zprava->cas_zachyceni), NULL, NULL, NULL, NULL);
		}
		else
		{
			vytvorena_iri = vytvor_iri(IRI_REPORT, OSCAR, Sezeni, TYP_ODHLASEN, USPESNE, &(zprava->cas_zachyceni), NULL, NULL, NULL, NULL);
		}
		odesli_iri(vytvorena_iri);
		free(vytvorena_iri);

		*aktualni_stav = NEPRIPOJEN;
		Sezeni->aktivni = 0;
		Sezeni->ukonceno = 1;
	}
}

