bool  tagDataBlockReadSet::GetBufferFromByteArray(CGUID& guid)
{
	long size = 0;
	GetBuff((uchar*)&size,1);
	if(size == 0)
	{
		guid = CGUID::GUID_INVALID;
		return false;
	}
	else
	{
		GetBuff((uchar*)&guid,sizeof(CGUID));
		return true;
	}
	return true;
}
char* tagDataBlockReadSet::GetStringFromByteArray(char* pStr, long lMaxLen)
{
	if(lMaxLen <= 1)	return NULL;
	long len = GetLongFromByteArray();
	if(len < 0)	len = 0;
	len = min(len,lMaxLen-1);
	GetBuff((uchar*)pStr,len);
	pStr[len] = '\0';
	return pStr;
}
void* tagDataBlockReadSet::GetBufferFromByteArray(void* pBuf, long lLen)
{
	GetBuff((uchar*)pBuf,lLen);
	return pBuf;
}
Exemple #4
0
/*

<SOH>00cG8BPQ:1025 G8BPQ:24 0 8 T60R6W108E06<EOT>
<SOH>00kG8BPQ:24 G8BPQ 4 85F9B<EOT>

<SOH>00cG8BPQ:1025 GM8BPQ:24 0 7 T60R5W1051D5<EOT> (128, 5)

,<SOH>00cG8BPQ:1025 G8BPQ:24 0 7 T60R5W10FA36<EOT>
<SOH>00kG8BPQ:24 G8BPQ 5 89FCA<EOT>

First no sees to be a connection counter. Next may be stream


<SOH>08s___ABFC<EOT>
<SOH>08tG8BPQ:73 xxx 33FA<EOT>
<SOH>00tG8BPQ:73 yyy 99A3<EOT>
<SOH>08dG8BPQ:90986C<EOT>
<SOH>00bG8BPQ:911207<EOT>

call:90 for dis 91 for dis ack 73<sp> for chat)

<SOH>08pG8BPQ<SUB>?__645E<EOT>
<SOH>00s_??4235<EOT>

<SOH>08pG8BPQ<SUB>?__645E<EOT>
<SOH>00s_??4235<EOT>

i Ident
c Connect
k Connect Ack
r Connect NAK
d Disconnect req
s Data Ack/ Retransmit Req )status)
p Poll
f Format Fail
b dis ack
t talk

a Abort
o Abort ACK


<SOH>00cG8BPQ:1025 G8BPQ:24 0 7 T60R5W10FA36<EOT>
<SOH>00kG8BPQ:24 G8BPQ 6 49A3A<EOT>
<SOH>08s___ABFC<EOT>
<SOH>08 ARQ:FILE::flarqmail-1.eml
ARQ:EMAIL::
ARQ:SIZE::90
ARQ::STX
//FLARQ COMPOSER
Date: 09/01/2014 23:24:42
To: gm8bpq
From: 
SubjectA0E0<SOH>
<SOH>08!: Test

Test Message

ARQ::ETX
F0F2<SOH>
<SOH>08pG8BPQ<SUB>!__623E<EOT>
<SOH>08pG8BPQ<SUB>!__623E<EOT>
<SOH>08pG8BPQ<SUB>!__623E<EOT>




*/
static VOID ProcessFLDigiData(struct TNCINFO * TNC, UCHAR * Input, int Len, int Stream)
{
	UINT * buffptr;
	struct STREAMINFO * STREAM = &TNC->Streams[Stream];
	char CTRL = Input[0];
	struct ARQINFO * ARQ = STREAM->ARQInfo;
	char Channel = Stream + 64;
	int SendLen;
	char Reply[80];

	Input[Len] = 0;

	// Process Message

	// This processes eitrher message from the KISS or RAW interfaces.
	//	Headers and RAW checksum have been removed, so packet starts with Control Byte

	// Only a connect request is allowed with no session, so check first

	if (CTRL == 'c')
	{
		// Connect Request

		char * call1;
		char * call2;
		char * port1;
		char * port2;
		char * ptr;
		char * context;
		char FarStream = 0;
		int BlockSize = 6;			// 64 default
		int Window = TNC->Window;		
		APPLCALLS * APPL;
		char * ApplPtr = APPLS;
		int App;
		char Appl[10];
		struct WL2KInfo * WL2K = TNC->WL2K;
		TRANSPORTENTRY * SESS;

		if (Stream)
			return;					// Shouldn't have Stream on Connect Request

		call1 = strtok_s(&Input[1], " ", &context);
		call2 = strtok_s(NULL, " ", &context);

		port1 = strlop(call1, ':');
		port2 = strlop(call2, ':');

		// See if for us

		for (App = 0; App < 32; App++)
		{
			APPL=&APPLCALLTABLE[App];
			memcpy(Appl, APPL->APPLCALL_TEXT, 10);
			ptr=strchr(Appl, ' ');

			if (ptr) *ptr = 0;
	
			if (_stricmp(call2, Appl) == 0)
					break;

			memcpy(Appl, APPL->APPLALIAS_TEXT, 10);
			ptr=strchr(Appl, ' ');

			if (ptr) *ptr = 0;
	
			if (_stricmp(call2, Appl) == 0)
					break;

		}

		if (App > 31)
			if (strcmp(TNC->NodeCall, call2) !=0)
				if (strcmp(call2, MYALIASLOPPED) !=0)
					return;				// Not Appl or Port/Node Call

		ptr =  strtok_s(NULL, " ", &context);
		FarStream = *ptr;
		ptr =  strtok_s(NULL, " ", &context);
		BlockSize = atoi(ptr);

		if (ARQ->ARQState > ARQ_CONNECTING)
		{
			// We have already received a connect request - just ACK it

			goto AckConnectRequest;
		}

		// Get a Session

		Stream = 1;

		while(Stream <= MAXARQ)
		{
			if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] == 0)
				goto GotStream;

			Stream++;
		}

		// No free streams - send Disconnect

		return;

	GotStream:

		STREAM = &TNC->Streams[Stream];

		ProcessIncommingConnect(TNC, call1, Stream, FALSE);
				
		SESS = TNC->PortRecord->ATTACHEDSESSIONS[Stream];

		strcpy(STREAM->MyCall, call2);
		STREAM->ConnectTime = time(NULL); 
		STREAM->BytesRXed = STREAM->BytesTXed = STREAM->BytesAcked = STREAM->BytesResent = 0;
		
		if (WL2K)
			strcpy(SESS->RMSCall, WL2K->RMSCall);

		ARQ = STREAM->ARQInfo;

		memset(ARQ, 0, sizeof(struct ARQINFO));		// Reset ARQ State
		ARQ->FarStream = FarStream;
		ARQ->TXSeq = ARQ->TXLastACK = 63;			// Last Sent
		ARQ->RXHighest = ARQ->RXNoGaps = 63;		// Last Received
		ARQ->ARQState = ARQ_ACTIVE;
		ARQ->OurStream = Stream + 64;

		STREAM->NeedDisc = 0;

		if (App < 32)
		{
			char AppName[13];

			memcpy(AppName, &ApplPtr[App * sizeof(CMDX)], 12);
			AppName[12] = 0;

			// Make sure app is available

			if (CheckAppl(TNC, AppName))
			{
				char Buffer[32];
				int MsgLen = sprintf(Buffer, "%s\r", AppName);

				buffptr = GetBuff();

				if (buffptr == 0)
				{
					return;			// No buffers, so ignore
				}

				buffptr[1] = MsgLen;
				memcpy(buffptr+2, Buffer, MsgLen);

				C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr);

				TNC->SwallowSignon = TRUE;

				// Save Appl Call in case needed for 

			}
			else
			{	
				STREAM->NeedDisc = 50;	// 1 sec
			}
		}
	
		ARQ->TXWindow = Window;

		if (BlockSize < 4)  BlockSize = 4;
		if (BlockSize < 9)  BlockSize = 9;

		ARQ->MaxBlock = Blocksizes[BlockSize];


		ARQ->ARQTimer = 1;			// To force CTEXT to be Queued
		
		if (App == 32)
		{
			// Connect to Node - send CTEXT

			if (HFCTEXTLEN > 1)
			{
				buffptr = GetBuff();
				if (buffptr)
				{
					buffptr[1] = HFCTEXTLEN;
					memcpy(&buffptr[2], HFCTEXT, HFCTEXTLEN);
					SendARQData(TNC, buffptr, Stream);
				}
			}
		}

		if (STREAM->NeedDisc)
		{
			// Send Not Avail 

			buffptr = GetBuff();
			if (buffptr)
			{
				buffptr[1] = sprintf((char *)&buffptr[2], "Application Not Available\r"); 
				SendARQData(TNC, buffptr, Stream);
			}
		}

		SetWindowText(STREAM->xIDC_MYCALL, STREAM->MyCall);
		SetWindowText(STREAM->xIDC_DESTCALL, STREAM->RemoteCall);
		SetWindowText(STREAM->xIDC_STATUS, "ConPending");
		SetWindowText(STREAM->xIDC_DIRN, "In");


AckConnectRequest:

		SendLen = sprintf(Reply, "k%s:24 %s %c 7", call2, call1, ARQ->OurStream); 

		SaveAndSend(TNC, ARQ, TNC->WINMORDataSock, Reply, SendLen);
		ARQ->ARQTimerState = ARQ_CONNECTACK;

		return;
	}

	// All others need a session

//	if (!STREAM->Connected && !STREAM->Connecting)
//		return;

	if (CTRL == 'k')
	{
		// Connect ACK

		char * call1;
		char * call2;
		char * port1;
		char * port2;
		char * ptr;
		char * context;
		char FarStream = 0;
		int BlockSize = 6;			// 64 default
		int Window = 16;
		
		char Reply[80];
		int ReplyLen;

		call1 = strtok_s(&Input[1], " ", &context);
		call2 = strtok_s(NULL, " ", &context);

		port1 = strlop(call1, ':');
		port2 = strlop(call2, ':');

		if (strcmp(call1, STREAM->RemoteCall) != 0)
			return;

		if (Channel != ARQ->OurStream)
			return;					// Wrong Session

		ptr =  strtok_s(NULL, " ", &context);
		if (ptr)
			FarStream = *ptr;
		ptr =  strtok_s(NULL, " ", &context);
		if (ptr)
			BlockSize = atoi(ptr);

		if (STREAM->Connected)
			goto SendKReply;		// Repeated ACK

		STREAM->ConnectTime = time(NULL); 
		STREAM->BytesRXed = STREAM->BytesTXed = STREAM->BytesAcked = STREAM->BytesResent = 0;
		STREAM->Connected = TRUE;

		ARQ->ARQTimerState = 0;
		ARQ->ARQTimer = 0;

		sprintf(TNC->WEB_TNCSTATE, "%s Connected to %s Outbound", STREAM->MyCall, STREAM->RemoteCall);
			
		SetWindowText(STREAM->xIDC_MYCALL, STREAM->MyCall);
		SetWindowText(STREAM->xIDC_DESTCALL, STREAM->RemoteCall);
		SetWindowText(STREAM->xIDC_DIRN, "Out");

		UpdateMH(TNC, STREAM->RemoteCall, '+', 'Z');
			
		ARQ->ARQTimerState = 0;
		ARQ->FarStream = FarStream;
		ARQ->TXWindow = TNC->Window;
		ARQ->MaxBlock = Blocksizes[BlockSize];

		ARQ->ARQState = ARQ_ACTIVE;

		STREAM->NeedDisc = 0;

		buffptr = GetBuff();

		if (buffptr)
		{
			ReplyLen = sprintf(Reply, "*** Connected to %s\r", STREAM->RemoteCall);

			buffptr[1] = ReplyLen;
			memcpy(buffptr+2, Reply, ReplyLen);

			C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr);
		}

		strcpy(TNC->WEB_PROTOSTATE, "Connected");
		SetWindowText(STREAM->xIDC_STATUS, "Connected");

SendKReply:

		// Reply with status

		SendLen = sprintf(Reply, "s%c%c%c", ARQ->TXSeq + 32, ARQ->RXNoGaps + 32, ARQ->RXHighest + 32);

		if (ARQ->RXHighest != ARQ->RXNoGaps)
		{
			int n = ARQ->RXNoGaps + 1;
			n &= 63;

			while (n != ARQ->RXHighest)
			{
				if (ARQ->RXHOLDQ[n] == 0)		// Dont have it
					SendLen += sprintf(&Reply[SendLen], "%c", n + 32);

				n++;
				n &= 63;
			}
		}

		QueueAndSend(TNC, ARQ, TNC->WINMORDataSock, Reply, SendLen);
		return;
	}

	// All others need a session

	//if (!STREAM->Connected)
	//	return;


	if (CTRL == 's')
	{
		// Status

		if (Channel != ARQ->OurStream)
			return;					// Wrong Session

		ARQ->ARQTimer = 0;			// Stop retry timer
		Input[Len] = 0;
		ProcessARQStatus(TNC, Stream, ARQ, &Input[1]);

		return;
	}

	if (CTRL == 'p')
	{
		// Poll

		char * call1;
		char * context;

		call1 = strtok_s(&Input[1], " \x1A", &context);

		if (strcmp(call1, STREAM->RemoteCall) != 0)
			return;

		if (Channel != ARQ->OurStream)
			return;					// Wrong Session

		Debugprintf("Sending Poll Resp TX NOGaps High %d %d %d", ARQ->TXSeq, ARQ->RXNoGaps, ARQ->RXHighest);

		SendLen = sprintf(Reply, "s%c%c%c", ARQ->TXSeq + 32, ARQ->RXNoGaps + 32, ARQ->RXHighest + 32);

		if (ARQ->RXHighest != ARQ->RXNoGaps)
		{
			int n = ARQ->RXNoGaps + 1;
			n &= 63;

			while (n != ARQ->RXHighest)
			{
				if (ARQ->RXHOLDQ[n] == 0)		// Dont have it
					SendLen += sprintf(&Reply[SendLen], "%c", n + 32);

				n++;
				n &= 63;
			}
		}
		else
			ARQ->TurnroundTimer = 15;			// Allow us to send it all acked

		QueueAndSend(TNC, ARQ, TNC->WINMORDataSock, Reply, SendLen);

		return;
	}


	if (CTRL == 'a')
	{
		// Abort. Send Abort ACK - same as 

		char * call1;
		char * context;

		call1 = strtok_s(&Input[1], " :", &context);

		if (strcmp(call1, STREAM->RemoteCall) != 0)
			return;

		if (Channel != ARQ->OurStream)
			return;					// Wrong Session

		SendLen = sprintf(Reply, "o%c%c%c", ARQ->TXSeq + 32, ARQ->RXNoGaps + 32, ARQ->RXHighest + 32);

		if (ARQ->RXHighest != ARQ->RXNoGaps)
		{
			int n = ARQ->RXNoGaps + 1;
			n &= 63;

			while (n != ARQ->RXHighest)
			{
				if (ARQ->RXHOLDQ[n] == 0)		// Dont have it
					SendLen += sprintf(&Reply[SendLen], "%c", n + 32);

				n++;
				n &= 63;
			}
		}

		QueueAndSend(TNC, ARQ, TNC->WINMORDataSock, Reply, SendLen);
		return;
	}

	if (CTRL == 'i')
	{
		// Ident

		return;
	}

	if (CTRL == 't')
	{
		// Talk - not sure what to do with these

		return;
	}

	if (CTRL == 'd')
	{
		// Disconnect Request

		char * call1;
		char * context;

		call1 = strtok_s(&Input[1], " ", &context);
		strlop(call1, ':');

		if (strcmp(STREAM->RemoteCall, call1))
			return;

		if (Channel != ARQ->OurStream)
			return;					// Wrong Session


		// As the Disc ACK isn't repeated, we have to clear session now

		STREAM->Connected = FALSE;
		STREAM->Connecting = FALSE;
		STREAM->ReportDISC = TRUE;

		strcpy(TNC->WEB_PROTOSTATE, "Disconncted");

		SetWindowText(STREAM->xIDC_MYCALL, "");
		SetWindowText(STREAM->xIDC_DESTCALL, "");
		SetWindowText(STREAM->xIDC_DIRN, "");
		SetWindowText(STREAM->xIDC_STATUS, "");
		
		ARQ->ARQState = 0;

		SendLen = sprintf(Reply, "b%s:91", STREAM->MyCall); 

		ARQ->ARQTimerState = ARQ_WAITACK;
		SaveAndSend(TNC, ARQ, TNC->WINMORDataSock, Reply, SendLen);
		ARQ->Retries = 2;
		return;
	}

	if (CTRL == 'b')
	{
		// Disconnect ACK

		char * call1;
		char * context;

		call1 = strtok_s(&Input[1], " ", &context);
		strlop(call1, ':');

		if (strcmp(STREAM->RemoteCall, call1))
			return;

		if (Channel != ARQ->OurStream)
			return;					// Wrong Session

		ARQ->ARQTimer = 0;
		ARQ->ARQTimerState = 0;
		ARQ->ARQState = 0;

		if (STREAM->Connected)
		{
			// Create a traffic record
		
			char logmsg[120];	
			time_t Duration;

			Duration = time(NULL) - STREAM->ConnectTime;
				
			if (Duration == 0)
				Duration = 1;
			
			sprintf(logmsg,"Port %2d %9s Bytes Sent %d  BPS %d Bytes Received %d BPS %d Time %d Seconds",
				TNC->Port, STREAM->RemoteCall,
				STREAM->BytesTXed, (int)(STREAM->BytesTXed/Duration),
				STREAM->BytesRXed, (int)(STREAM->BytesRXed/Duration), (int)Duration);

			Debugprintf(logmsg);
		}

		STREAM->Connecting = FALSE;
		STREAM->Connected = FALSE;		// Back to Command Mode
		STREAM->ReportDISC = TRUE;		// Tell Node

		STREAM->Disconnecting = FALSE;

		strcpy(TNC->WEB_PROTOSTATE, "Disconncted");
		SetWindowText(STREAM->xIDC_MYCALL, "");
		SetWindowText(STREAM->xIDC_DESTCALL, "");
		SetWindowText(STREAM->xIDC_DIRN, "");
		SetWindowText(STREAM->xIDC_STATUS, "");

		return;
	}

	if (CTRL == 'u')
	{
		// Beacon

		//>00uGM8BPQ:72 GM8BPQ TestingAD67

		char * Call = &Input[1];
		strlop(Call, ':');

		UpdateMH(TNC, Call, '!', 0);
		return;
	}

	if (STREAM->Connected)
	{
		if (Channel != ARQ->OurStream)
			return;					// Wrong Session

		if (CTRL >= ' ' && CTRL < 96)
		{
			// ARQ Data

			int Seq = CTRL - 32;
			int Work;

//			if (rand() % 5 == 2)
//			{
//				Debugprintf("Dropping %d", Seq);
//				return; 
//			}

			buffptr = GetBuff();
	
			if (buffptr == NULL)
				return;				// Sould never run out, but cant do much else

			// Remove any DLE transparency

			Len -= 1;

			buffptr[1]  = Len;
			memcpy(&buffptr[2], &Input[1], Len);
			STREAM->BytesRXed += Len;

			UpdateStatsLine(TNC, STREAM);

			// Safest always to save, then see what we can process

			if (ARQ->RXHOLDQ[Seq])
			{
				// Wot! Shouldn't happen

				ReleaseBuffer(ARQ->RXHOLDQ[Seq]);
//				Debugprintf("ARQ Seq %d Duplicate");
			}

			ARQ->RXHOLDQ[Seq] = buffptr;
//			Debugprintf("ARQ saving %d", Seq);

			// If this is higher that highest received, save. But beware of wrap'

			// Hi = 2, Seq = 60  dont save s=h = 58
			// Hi = 10 Seq = 12	 save s-h = 2
			// Hi = 14 Seq = 10  dont save s-h = -4
			// Hi = 60 Seq = 2	 save s-h = -58

			Work = Seq - ARQ->RXHighest;

			if ((Work > 0 && Work < 32) || Work < -32)
				ARQ->RXHighest = Seq;

			// We may now be able to process some

			Work = (ARQ->RXNoGaps + 1) & 63;		// The next one we need

			while (ARQ->RXHOLDQ[Work])
			{
				// We have it

				C_Q_ADD(&STREAM->PACTORtoBPQ_Q, ARQ->RXHOLDQ[Work]);
//				ReleaseBuffer(ARQ->RXHOLDQ[Work]);

				ARQ->RXHOLDQ[Work] = NULL;
//				Debugprintf("Processing %d from Q", Work);

				ARQ->RXNoGaps = Work;
				Work = (Work + 1) & 63;		// The next one we need
			}

			ARQ->TurnroundTimer = 200;		// Delay before allowing reply. Will normally be reset by the poll following data
			return;
		}
	}
}
Exemple #5
0
static VOID ARQTimer(struct TNCINFO * TNC)
{
	UINT * buffptr;
	struct STREAMINFO * STREAM;
	struct ARQINFO * ARQ;
	int SendLen;
	char Reply[80];
	int Stream;

	//Send frames, unless held by TurnroundTimer or Window

	int Outstanding;

	for (Stream = 0; Stream <MAXARQ; Stream++)
	{
		STREAM = &TNC->Streams[Stream];
		ARQ = STREAM->ARQInfo;

		//	TXDelay is used as a turn round delay for frames that don't have to be retried. It doesn't
		//	need to check for busy (or anything else (I think!)

	if (ARQ->TXDelay)
	{
		ARQ->TXDelay--;

		if (ARQ->TXDelay)
			continue;

		SendPacket(TNC, STREAM, ARQ->TXMsg, ARQ->TXLen);
	}

	// if We are alredy sending (State = ARQ_WAITDATA) we should allow it to send more (and the Poll at end)

	if (ARQ->ARQTimerState == ARQ_WAITDATA)
	{
		while (STREAM->BPQtoPACTOR_Q)
		{
			Outstanding = ARQ->TXSeq - ARQ->TXLastACK;
		
			if (Outstanding < 0)
				Outstanding += 64;

			TNC->PortRecord->FramesQueued = Outstanding + STREAM->BPQtoPACTOR_Q;		// Save for Appl Level Queued Frames

			if (Outstanding >= ARQ->TXWindow)
				break;
		
			buffptr = Q_REM(&STREAM->BPQtoPACTOR_Q);
			SendARQData(TNC, buffptr, Stream);
		}

		ARQ->ARQTimer--;

		if (ARQ->ARQTimer > 0)
			continue;					// Timer Still Running
	
		// No more data available - send poll 

		SendLen = sprintf(Reply, "p%s", STREAM->MyCall);

		ARQ->ARQTimerState = ARQ_WAITACK;

		// This is one message that should not be queued so it is sent straiget after data

		Debugprintf("Sending Poll After Data");

		memcpy(ARQ->LastMsg, Reply, SendLen + 1);
		ARQ->LastLen = SendLen;

		SendPacket(TNC, STREAM, Reply, SendLen);
		
		ARQ->ARQTimer = TNC->Timeout;
		ARQ->Retries = TNC->Retries;

		strcpy(TNC->WEB_PROTOSTATE, "Wait ACK");
		SetWindowText(STREAM->xIDC_STATUS, "Wait ACK");

		continue;
	
	}

	// TrunroundTimer is used to allow time for far end to revert to RX

	if (ARQ->TurnroundTimer)
		ARQ->TurnroundTimer--;

	if (ARQ->TurnroundTimer == 0)
	{
		while (STREAM->BPQtoPACTOR_Q)
		{
			Outstanding = ARQ->TXSeq - ARQ->TXLastACK;
		
			if (Outstanding < 0)
				Outstanding += 64;

			TNC->PortRecord->FramesQueued = Outstanding + STREAM->BPQtoPACTOR_Q + 1; // Make sure busy is reported to BBS

			if (Outstanding >= ARQ->TXWindow)
				break;
		
			buffptr = Q_REM(&STREAM->BPQtoPACTOR_Q);
			SendARQData(TNC, buffptr, Stream);
		}
	}

	if (ARQ->ARQTimer)
	{
		// Only decrement if running send poll timer
			
//		if (ARQ->ARQTimerState != ARQ_WAITDATA)
//			return;

		ARQ->ARQTimer--;
		{
			if (ARQ->ARQTimer)
				continue;					// Timer Still Running
		}

		ARQ->Retries--;

		if (ARQ->Retries)
		{
			// Retry Current Message

			SendPacket(TNC, STREAM, ARQ->LastMsg, ARQ->LastLen);
			ARQ->ARQTimer = TNC->Timeout + (rand() % 30);

			continue;
		}

		// Retried out.

		switch (ARQ->ARQTimerState)
		{
		case ARQ_WAITDATA:

			// No more data available - send poll 

			SendLen = sprintf(Reply, "p%s", STREAM->MyCall);

			Debugprintf("Sending Poll After Timeout??");

			ARQ->ARQTimerState = ARQ_WAITACK;

			// This is one message that should not be queued so it is sent straiget after data

			memcpy(ARQ->LastMsg, Reply, SendLen + 1);
			ARQ->LastLen = SendLen;

			SendPacket(TNC, STREAM, Reply, SendLen);
		
			ARQ->ARQTimer = TNC->Timeout;
			ARQ->Retries = TNC->Retries;

			strcpy(TNC->WEB_PROTOSTATE, "Wait ACK");
			SetWindowText(STREAM->xIDC_STATUS, "Wait ACK");

			continue;
	
		case ARQ_CONNECTING:

			// Report Connect Failed, and drop back to command mode

			buffptr = GetBuff();

			if (buffptr)
			{
				buffptr[1] = sprintf((UCHAR *)&buffptr[2], "UIARQ} Failure with %s\r", STREAM->RemoteCall);
				C_Q_ADD(&STREAM->PACTORtoBPQ_Q, buffptr);
			}
	
			// Send Disc to TNC in case it got the Connects, but we missed the ACKs

			TidyClose(TNC, Stream);
			ARQ->Retries = 2;				// First timout is the real send, only send once
			STREAM->Connecting = FALSE;		// Back to Command Mode
			ARQ->ARQState = FALSE;

			break;

		case ARQ_WAITACK:
		case ARQ_CONNECTACK:
		case ARQ_DISC:
		
			STREAM->Connected = FALSE;		// Back to Command Mode
			STREAM->ReportDISC = TRUE;	
			ARQ->ARQState = FALSE;

			while (STREAM->PACTORtoBPQ_Q)
				ReleaseBuffer(Q_REM(&STREAM->PACTORtoBPQ_Q));
	
			while (STREAM->BPQtoPACTOR_Q)
				ReleaseBuffer(Q_REM(&STREAM->BPQtoPACTOR_Q));
	
			strcpy(TNC->WEB_TNCSTATE, "Free");

			strcpy(TNC->WEB_PROTOSTATE, "Disconncted");
		
			SetWindowText(STREAM->xIDC_MYCALL, "");
			SetWindowText(STREAM->xIDC_DESTCALL, "");
			SetWindowText(STREAM->xIDC_DIRN, "");
			SetWindowText(STREAM->xIDC_STATUS, "");

			break;

		}
	}
	}
}
Exemple #6
0
static int ExtProc(int fn, int port,unsigned char * buff)
{
	UINT * buffptr;
	unsigned int txlen=0;
	struct TNCINFO * TNC = TNCInfo[port];
	int Stream = 0;
	struct STREAMINFO * STREAM;

	if (TNC == NULL)
		return 0;					// Port not defined

	// Look for attach on any call

	for (Stream = 0; Stream <= MAXARQ; Stream++)
	{
		STREAM = &TNC->Streams[Stream];
	
		if (TNC->PortRecord->ATTACHEDSESSIONS[Stream] && TNC->Streams[Stream].Attached == 0)
		{
			// New Attach

			int calllen;
			STREAM->Attached = TRUE;

			calllen = ConvFromAX25(TNC->PortRecord->ATTACHEDSESSIONS[Stream]->L4USER, STREAM->MyCall);
			STREAM->MyCall[calllen] = 0;
			STREAM->FramesOutstanding = 0;

			SetWindowText(STREAM->xIDC_STATUS, "Attached");
			SetWindowText(STREAM->xIDC_MYCALL, STREAM->MyCall);
	
		}
	}

	switch (fn)
	{
	case 7:			

		// 100 mS Timer. 

		for (Stream = 0; Stream <= MAXARQ; Stream++)
		{
			STREAM = &TNC->Streams[Stream];
	
			if (STREAM->NeedDisc)
			{
				STREAM->NeedDisc--;

				if (STREAM->NeedDisc == 0)
				{
					// Send the DISCONNECT

					TidyClose(TNC, Stream);
				}
			}
		}
	
		ARQTimer(TNC);
	
		return 0;

	case 1:				// poll

		// See if any frames for this port

		for (Stream = 0; Stream <= MAXARQ; Stream++)
		{
			STREAM = &TNC->Streams[Stream];
			
			if (STREAM->Attached)
				CheckForDetach(TNC, Stream, STREAM, TidyClose, ForcedClose, CloseComplete);

			if (STREAM->ReportDISC)
			{
				STREAM->ReportDISC = FALSE;
				buff[4] = Stream;

				return -1;
			}
	
			if (STREAM->PACTORtoBPQ_Q == 0)
			{
				if (STREAM->DiscWhenAllSent)
				{
					STREAM->DiscWhenAllSent--;
					if (STREAM->DiscWhenAllSent == 0)
						STREAM->ReportDISC = TRUE;				// Dont want to leave session attached. Causes too much confusion
				}
			}
			else
			{
				int datalen;
			
				buffptr=Q_REM(&STREAM->PACTORtoBPQ_Q);

				datalen=buffptr[1];

				buff[4] = Stream;
				buff[7] = 0xf0;
				memcpy(&buff[8],buffptr+2,datalen);		// Data goes to +7, but we have an extra byte
				datalen+=8;
				
				PutLengthinBuffer(buff, datalen);
		
				ReleaseBuffer(buffptr);
	
				return (1);
			}
		}

		if (TNC->PortRecord->UI_Q)
		{
			struct _MESSAGE * buffptr;
			int SendLen;
			char Reply[256];
			int UILen;
			char * UIMsg;

			buffptr = Q_REM(&TNC->PortRecord->UI_Q);

			UILen = buffptr->LENGTH;
			UILen -= 23;
			UIMsg = buffptr->L2DATA;

			UIMsg[UILen] = 0;

			if (UILen < 129 && STREAM->Attached == FALSE)			// Be sensible!
			{
				// >00uG8BPQ:72 TestA
				SendLen = sprintf(Reply, "u%s:72 %s", TNC->NodeCall, UIMsg);
				SendPacket(TNC, STREAM, Reply, SendLen);
			}
			ReleaseBuffer(buffptr);
		}
			
		return (0);

	case 2:				// send

	
		Stream = buff[4];
		
		STREAM = &TNC->Streams[Stream]; 

//		txlen=(buff[6]<<8) + buff[5] - 8;	

		txlen = GetLengthfromBuffer(buff) - 8;
				
		if (STREAM->Connected)
		{
			buffptr = GetBuff();

			if (buffptr == 0) return (0);			// No buffers, so ignore
		
			buffptr[1] = txlen;
			memcpy(buffptr+2, &buff[8], txlen);
		
			C_Q_ADD(&TNC->Streams[Stream].BPQtoPACTOR_Q, buffptr);

			return (0);
		}
		else
		{
			buff[8 + txlen] = 0;
			_strupr(&buff[8]);

			if (_memicmp(&buff[8], "D\r", 2) == 0)
			{
				if (STREAM->Connected)
					TidyClose(TNC, buff[4]);

				STREAM->ReportDISC = TRUE;		// Tell Node
				return 0;
			}

			// See if a Connect Command.

			if (toupper(buff[8]) == 'C' && buff[9] == ' ' && txlen > 2)	// Connect
			{
				char * ptr;
				char * context;
				struct ARQINFO * ARQ = STREAM->ARQInfo;
				int SendLen;
				char Reply[80];

				_strupr(&buff[8]);
				buff[8 + txlen] = 0;

				memset(ARQ, 0, sizeof(struct ARQINFO));		// Reset ARQ State
				ARQ->TXSeq = ARQ->TXLastACK = 63;			// Last Sent
				ARQ->RXHighest = ARQ->RXNoGaps = 63;		// Last Received
				ARQ->OurStream = Stream + 64;
				ARQ->FarStream = 64;						// Not yet defined

				memset(STREAM->RemoteCall, 0, 10);

				ptr = strtok_s(&buff[10], " ,\r", &context);
				strcpy(STREAM->RemoteCall, ptr);

//<SOH>00cG8BPQ:1025 G8BPQ:24 0 7 T60R5W10FA36<EOT>

				SendLen = sprintf(Reply, "c%s:42 %s:24 %c 7 T60R5W10",
					STREAM->MyCall, STREAM->RemoteCall, ARQ->OurStream); 

				ARQ->ARQState = ARQ_ACTIVE;

				ARQ->ARQTimerState = ARQ_CONNECTING;
				SaveAndSend(TNC, ARQ, TNC->WINMORDataSock, Reply, SendLen);

				SetWindowText(STREAM->xIDC_STATUS, "Connecting");
				SetWindowText(STREAM->xIDC_MYCALL, STREAM->MyCall);
				SetWindowText(STREAM->xIDC_DESTCALL, STREAM->RemoteCall);
				SetWindowText(STREAM->xIDC_DIRN, "Out");

				STREAM->Connecting = TRUE;	

				return 0;
			}
		}
		return (0);

	case 3:	

		Stream = (int)buff;

		STREAM = &TNC->Streams[Stream];
		{
			// Busy if TX Window reached

			struct ARQINFO * ARQ = STREAM->ARQInfo;
			int Outstanding;

			Outstanding = ARQ->TXSeq - ARQ->TXLastACK;

			if (Outstanding < 0)
				Outstanding += 64;

			TNC->PortRecord->FramesQueued = Outstanding + C_Q_COUNT(&STREAM->BPQtoPACTOR_Q);		// Save for Appl Level Queued Frames

			if (Outstanding > ARQ->TXWindow)
				return (1 | 1 << 8 | STREAM->Disconnecting << 15); // 3rd Nibble is frames unacked
			else
				return 1 << 8 | STREAM->Disconnecting << 15;

		}
		return 1 << 8 | STREAM->Disconnecting << 15;		// OK, but lock attach if disconnecting
	
	case 4:				// reinit

		return (0);

	case 5:				// Close

		return 0;
	}

	return 0;
}
Exemple #7
0
DllExport UINT APIENTRY SoundCardInterface(int CardNo, int Function, UINT Param1, UINT Param2)
{
	UINT * buffptr;
	L1FRAME * rxf;

	switch (Function)
	{
	case INIT:	
		SoundCardList[CardNo].PID = Param1;
		Debugprintf("SoundCard %d PID %d", CardNo, Param1);
		break;

	case CHECKCHAN:

		Debugprintf("CheckChan %d %d = %d", CardNo, Param1,  SoundCardList[CardNo].Channellist[Param1].BPQPort); 

		return SoundCardList[CardNo].Channellist[Param1].BPQPort;	// Nonzero if port is configured

	case GETBUFFER:
		return (UINT)GetBuff();

	case POLL:

		// See if anything on the TXQ

		SoundCardList[CardNo].State = Param1;		// PTT and DCD State bits
		buffptr = Q_REM(&SoundCardList[CardNo].TXQ);

		if (buffptr)
		{
			memcpy((void *)Param2, buffptr, buffptr[1] + 12);
			ReleaseBuffer(buffptr);
			return 1;
		}

		return 0;


	case RXPACKET:

		// A received Packet. Param1 is buffer, Param2 the channel

		buffptr = GetBuff();

		if (buffptr)
		{
			rxf = (L1FRAME *)Param1;

			buffptr[1] = rxf->len;
			memcpy(buffptr+2, rxf->frame, rxf->len);

			C_Q_ADD(&RXQ[SoundCardList[CardNo].Channellist[Param2].BPQPort], buffptr);
		}
		
		break;

	case CLOSING:

		SoundCardList[CardNo].ProcessMonitor = 250;		// Restart in 5 secs
		break;
	}
	return 0;
}
Exemple #8
0
static int ExtProc(int fn, int port, unsigned char * buff)
{
	int len = 0, txlen=0;
	struct CHANNELINFO * PORT = Portlist[port];
	struct PORTCONTROL * PORTVEC = PORT->PORTVEC;
	struct SOUNDTNCINFO * TNC = PortToTNC[port];
	int State = TNC->State;
	UINT * buffptr;

	switch (fn)
	{
	case 1:				// poll

		TNC->ProcessMonitor++;
		
		if (TNC->ProcessMonitor > 300)
		{
			TNC->ProcessMonitor = 0;
			
			if (TNC->PID)
			{
				HANDLE hProc;
				hProc =  OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, TNC->PID);

				if (hProc)
				{	
					DWORD ExitCode = 0;

					GetExitCodeProcess(hProc, &ExitCode);
					if (ExitCode != STILL_ACTIVE)
						RestartSoundTNC(TNC);

 					CloseHandle(hProc);
				}
			}
			else
				RestartSoundTNC(TNC);
		}
	
		if (State & 0x20)
			PORTVEC->SENDING++;

		if (State & 0x10)
			PORTVEC->ACTIVE++;

		buffptr = Q_REM(&RXQ[port]);

		if (buffptr)
		{
			len = buffptr[1];

			memcpy(&buff[7], &buffptr[2], len);
			len+=7;
			buff[5]=(len & 0xff);
			buff[6]=(len >> 8);

			ReleaseBuffer(buffptr);

			return len;
		}

		return 0;

	case 2: // send

		buffptr = GetBuff();
			
		if (buffptr == 0) return (0);			// No buffers, so ignore

		txlen = (buff[6] <<8 ) + buff[5] - 7;	
		buffptr[1] = txlen;
		buffptr[2] = PortToChannel[port];		// Channel on this Soundcard
		memcpy(buffptr+3, &buff[7], txlen);

		C_Q_ADD(&TNC->TXQ, buffptr);

		return 0;


	case 3:				// CHECK IF OK TO SEND

		return (0);		// OK

	case 4:				// reinit

		return (0);		// OK
			
	case 5:				// Close

		if (TNC->PID)
		{
			KillSoundTNC(TNC);			
			if (AUTOSAVE == 1) SaveNodes();	
			Sleep(1000);
		}

		return (0);

	}

	return 0;

}