/*****************************************************************************
* IPX.C
*
* 91-04-05 Matt Hagen, Novell, Inc.
*****************************************************************************/

#include "ipx.h"

/*****************************************************************************
* AllocateIPXResources
*****************************************************************************/

SESSION *AllocateIPXResources(
	WORD socketValue,
	BYTE semaphoreValue,
	BYTE rxCount,
	LONG rxDataSize,
	BYTE txCount,
	LONG txDataSize)
{
	int a;
	SESSION *s;
	ECBHOLD *h;

	s=malloc(sizeof(SESSION));
	if(s==NULL)
		goto error0;

	s->semaphore=OpenLocalSemaphore(semaphoreValue);
	if(s->semaphore==NULL)
		goto error1;

	s->socket=socketValue;
	s->rxHead=NULL;
	s->rxList=NULL;
	s->txList=NULL;

	if(IpxOpenSocket(&s->socket)!=ESUCCESS)
		goto error2;

	for(a=0;a<rxCount;a++)
	{
		h=AllocatePacket(rxDataSize,s->socket,s->semaphore,&s->rxHead);
		if(h==NULL)
			goto error3;

		h->fLink=s->rxList;
		s->rxList=h;

		if(IpxReceive(NULL,h->ecb)!=ESUCCESS)
			goto error3;
	}

	for(a=0;a<txCount;a++)
	{
		h=AllocatePacket(txDataSize,s->socket,NULL,NULL);
		if(h==NULL)
			goto error4;

		h->fLink=s->txList;
		s->txList=h;
	}

	return(s);

error4:;
	while(s->txList!=NULL)
	{
		h=s->txList;
		s->txList=h->fLink;
		DeallocatePacket(h);
	}

error3:;
	IpxCloseSocket(s->socket);

	while(s->rxList!=NULL)
	{
		h=s->rxList;
		s->rxList=h->fLink;
		DeallocatePacket(h);
	}

error2:;
	CloseLocalSemaphore(s->semaphore);

error1:;
	free(s);

error0:;
	return(NULL);
}

/*****************************************************************************
* DeallocateIPXResources
*****************************************************************************/

void DeallocateIPXResources(
	SESSION *s)
{
	ECBHOLD *h;

	while(s->txList!=NULL)
	{
		h=s->txList;
		s->txList=h->fLink;
		DeallocatePacket(h);
	}

	IpxCloseSocket(s->socket);

	while(s->rxList!=NULL)
	{
		h=s->rxList;
		s->rxList=h->fLink;
		DeallocatePacket(h);
	}

	CloseLocalSemaphore(s->semaphore);

	free(s);
}

/*****************************************************************************
* AllocatePacket
*****************************************************************************/

ECBHOLD *AllocatePacket(
	LONG dataSize,
	WORD socket,
	LONG semaphore,
	IPX_ECB **head)
{
	ECBHOLD *h;
	IPX_ECB *ecb;

	h=malloc(sizeof(ECBHOLD));
	if(h==NULL)
		goto error0;

	ecb=malloc(sizeof(IPX_ECB));
	if(ecb==NULL)
		goto error1;

	ecb->fragList[0].fragAddress=malloc(sizeof(IPX_HEADER));
	if(ecb->fragList[0].fragAddress==NULL)
		goto error2;

	ecb->fragList[1].fragAddress=malloc(dataSize);
	if(ecb->fragList[1].fragAddress==NULL)
		goto error3;

	ecb->queueHead=head;
	ecb->semHandle=semaphore;
	ecb->socket=socket;
	ecb->fragCount=2;
	ecb->fragList[0].fragSize=sizeof(IPX_HEADER);
	ecb->fragList[1].fragSize=dataSize;
	((IPX_HEADER *)(ecb->fragList[0].fragAddress))->packetType=NULL;

	h->ecb=ecb;
	return(h);

error3:;
	free(ecb->fragList[0].fragAddress);

error2:;
	free(ecb);

error1:;
	free(h);

error0:;
	return(NULL);
}

/*****************************************************************************
* DeallocatePacket
*****************************************************************************/

void DeallocatePacket(
	ECBHOLD *h)
{
	free(h->ecb->fragList[1].fragAddress);
	free(h->ecb->fragList[0].fragAddress);
	free(h->ecb);
	free(h);
}

/****************************************************************************/
/****************************************************************************/
