#include <vcl.h>
#include <stdio.h>
#include <mmsystem.h>
#pragma hdrstop
#include "Form_Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"

TWin_Main *Win_Main;
//---------------------------------------------------------------------------
__fastcall TWin_Main::TWin_Main(TComponent* Owner)
	: TForm(Owner)
{
	SendSize	= 0;
    RecvSize	= 0;

    SpeedTimer	= timeGetTime();

    for(int i = 0; i < 100; i++)
    	lpContext[i]	= NULL;
}

//---------------------------------------------------------------------------
// 시작
//---------------------------------------------------------------------------
void __fastcall TWin_Main::FormCreate(TObject *Sender)
{
	TCPServer->Active	= true;

	Cs	= new TCriticalSection;
}

//---------------------------------------------------------------------------
// 종료
//---------------------------------------------------------------------------
void __fastcall TWin_Main::FormClose(TObject *Sender, TCloseAction &Action)
{
	delete Cs;
}

//---------------------------------------------------------------------------
void __fastcall TWin_Main::TCPServerExecute(TIdContext *AContext)
{
	int				HEADER_SIZE	= 12;
    int				Cmd, Size, Check;
    BYTE			Buffer[65535];
    TMemoryStream	*RecvStream	= new TMemoryStream, *SendStream = new TMemoryStream;
    TList 			*lpList;

	__try
    {
    	if(!AContext->Connection || !AContext->Connection->Connected())
            return;

    	__try
        {
            AContext->Connection->IOHandler->ReadStream(RecvStream);
            RecvStream->Position	= 0;

            // 읽은 패킷 처리
            while(RecvStream->Position < RecvStream->Size)
            {
                // 헤더 읽기 (패킷 종류, 크기, 무결성 체크)
                RecvStream->ReadBuffer(&Cmd, sizeof(int));
                RecvStream->ReadBuffer(&Size, sizeof(int));
                RecvStream->ReadBuffer(&Check, sizeof(int));

                // 에러 검사
                if(Size != Check + 1)
                {
                    printf("ERROR : 패킷 무결성 에러 - %d, %d\n", Cmd, Size);

                    AContext->Connection->Disconnect();
                    AContext->Connection->IOHandler->InputBuffer->Clear();

                    return;
                }

                // 나머지 읽기
                RecvStream->Read(Buffer, Size);

                // 패킷 처리
                switch(Cmd)
                {
                case 0xBFCF:
                	SendStream->Clear();
                    SendStream->Write(&Cmd, sizeof(int));
                    SendStream->Write(&Size, sizeof(int));
                    SendStream->Write(&Check, sizeof(int));
                    SendStream->Write(Buffer, Size);

					lpList	= TCPServer->Contexts->LockList();

                    for(int i = 0; i < lpList->Count; i++)
                    {
                    	TIdContext *lpContext	= (TIdContext *)lpList->Items[i];

                        SendStream->Position	= 0;
                        lpContext->Connection->IOHandler->Write(SendStream, 0, true);

                        // 보내는 속도 측정
                        SendSize += (HEADER_SIZE + Size);
                    }

                    TCPServer->Contexts->UnlockList();

                    break;
                default:
                    printf("ERROR : 알 수 없는 패킷 %d\n", Cmd);

                    AContext->Connection->Disconnect();
                    AContext->Connection->IOHandler->InputBuffer->Clear();

                    return;
                }
            }

            // 받기 속도 측정
            RecvSize += (HEADER_SIZE + Size);

            if(timeGetTime() - SpeedTimer > 1000)
            {
                SpeedTimer	= timeGetTime();

                printf("[속도] 접속 수 : %d     보내기 : %.2fKB     받기 : %.2fKB\n", UserCount, SendSize / 1024.0f, RecvSize / 1024.0f);

                SendSize	= 0;
                RecvSize	= 0;
            }
        }
		// 정상 종료
        catch(EIdClosedSocket& e)
        {
             AContext->Connection->Disconnect();
             AContext->Connection->IOHandler->InputBuffer->Clear();
        }
        catch(EIdException& e)
        {
            if(e.Message.Pos("racefully") <= 0)
                printf("ERROR : 접속 해제 #1 - %s\n", e.Message.t_str());

            AContext->Connection->Disconnect();
            AContext->Connection->IOHandler->InputBuffer->Clear();
        }
        // 지정 오류
        catch(Exception& e)
        {
            printf("ERROR : 접속 해제 #2 - %s\n", e.Message.t_str());

            AContext->Connection->Disconnect();
            AContext->Connection->IOHandler->InputBuffer->Clear();
        }
        // 알 수 없는 오류
        catch(...)
        {
            printf("ERROR : 접속 해제 #3\n");

            AContext->Connection->Disconnect();
            AContext->Connection->IOHandler->InputBuffer->Clear();
        }
    }
    __finally
    {
        delete RecvStream;
        delete SendStream;
    }
}

//---------------------------------------------------------------------------
// 접속
//---------------------------------------------------------------------------
void __fastcall TWin_Main::TCPServerConnect(TIdContext *AContext)
{
	lpContext[UserCount]	= AContext;
	UserCount++;

    printf("CONNECT : %d\n", UserCount);
}

//---------------------------------------------------------------------------
// 접속 해제
//---------------------------------------------------------------------------
void __fastcall TWin_Main::TCPServerDisconnect(TIdContext *AContext)
{
	UserCount--;

    printf("DISCONNECT : %d\n", UserCount);
}
//---------------------------------------------------------------------------

