Esempio n. 1
0
void TransferCaptaincyUpdate(void)
{
    udword numPackets;
    udword sizeofPacket;
    ubyte *packet;
    ubyte *copypacket;

    if ((transferCaptaincyDisabled) || (sigsNumPlayers < 2))
    {
        return;
    }

    TimeoutTimerUpdateAll();

    LockQueue(&ProcessCaptaincyPktQ);
    numPackets = queueNumberEntries(ProcessCaptaincyPktQ);

    while (numPackets > 0)
    {
        sizeofPacket = Dequeue(&ProcessCaptaincyPktQ,&packet);
        dbgAssert(sizeofPacket > 0);
        copypacket = memAlloc(sizeofPacket,"cp(miscpacket)",Pyrophoric);
        memcpy(copypacket,packet,sizeofPacket);
        UnLockQueue(&ProcessCaptaincyPktQ);

        dbgAssert(((HWPacketHeader *)copypacket)->type == PACKETTYPE_TRANSFERCAPTAINCY);
        ProcessTransferCaptaincyPacket((TransferCaptaincyPacket *)copypacket);
        memFree(copypacket);

        LockQueue(&ProcessCaptaincyPktQ);
        numPackets = queueNumberEntries(ProcessCaptaincyPktQ);
    }

    UnLockQueue(&ProcessCaptaincyPktQ);

#if 0
    if (numPackets == 0)
    {
        UnLockQueue(&ProcessCaptaincyPktQ);
    }
    else
    {
        sizeofPacket = Dequeue(&ProcessCaptaincyPktQ,&packet);
        dbgAssert(sizeofPacket > 0);
        copypacket = memAlloc(sizeofPacket,"cp(miscpacket)",Pyrophoric);
        memcpy(copypacket,packet,sizeofPacket);
        UnLockQueue(&ProcessCaptaincyPktQ);

        dbgAssert(((HWPacketHeader *)copypacket)->type == PACKETTYPE_TRANSFERCAPTAINCY);
        ProcessTransferCaptaincyPacket((TransferCaptaincyPacket *)copypacket);
        memFree(copypacket);
    }
#endif
}
Esempio n. 2
0
// パケットアダプタの解放
void LinkPaFree(SESSION *s)
{
	LINK *k;
	// 引数チェック
	if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
	{
		return;
	}

	// サーバーセッションの停止
	StopSession(k->ServerSession);
	ReleaseSession(k->ServerSession);

	// 送信パケットキューの解放
	LockQueue(k->SendPacketQueue);
	{
		BLOCK *block;
		while (block = GetNext(k->SendPacketQueue))
		{
			FreeBlock(block);
		}
	}
	UnlockQueue(k->SendPacketQueue);

	ReleaseQueue(k->SendPacketQueue);
}
Esempio n. 3
0
//
//Finds the first occurrence of a queue element based on the predicate and 
//removes it from the queue
//
QueueElementData Queue_RemoveElement(PQueue pQueue, void * predicate, DoesMatch pDoesMatchFunc)
{
	QueueElementData data = NULL;
	PQueueElement currItem = NULL;

	if(!pQueue)
	{
		return NULL;
	}

	LockQueue(pQueue);

	if (NULL == pQueue->pHead)
	{
		UnLockQueue(pQueue);
		return NULL;
	}

	currItem = pQueue->pHead;
	while (currItem != NULL)
	{
		if (pDoesMatchFunc(currItem->data, predicate) == TRUE)
		{
			data = Queue_RemoveElementInternal(pQueue, currItem);
			break;
		}

		currItem = currItem->pNextItem;
	}

	UnLockQueue(pQueue);

	return data;
}
Esempio n. 4
0
extern	Bool
EnQueue(
	Queue	*que,
	void	*data)
{
	QueueElement	*el;
	Bool	rc;

ENTER_FUNC;
	if		(	(  que             !=  NULL  )
			&&	(  LockQueue(que)  ==  0     ) ) {
		el = New(QueueElement);
		el->data = data;
		el->prev = que->tail;
		el->next = NULL;
		if		(  que->tail  ==  NULL  ) {
			que->head = el;
		} else {
			que->tail->next = el;
		}
		que->tail = el;
		que->length++;
		UnLockQueue(que);
		ReleaseQueue(que);
		rc = TRUE;
	} else {
		rc = FALSE;
	}
LEAVE_FUNC;
	return	(rc);
}
Esempio n. 5
0
// Get the next packet
UINT LinkPaGetNextPacket(SESSION *s, void **data)
{
	LINK *k;
	UINT ret = 0;
	// Validate arguments
	if (s == NULL || data == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
	{
		return INFINITE;
	}

	// Examine whether there are packets in the queue
	LockQueue(k->SendPacketQueue);
	{
		BLOCK *block = GetNext(k->SendPacketQueue);

		if (block != NULL)
		{
			// There was a packet
			*data = block->Buf;
			ret = block->Size;
			// Discard the memory for the structure
			Free(block);
		}
	}
	UnlockQueue(k->SendPacketQueue);

	return ret;
}
Esempio n. 6
0
// Release the packet adapter
void LinkPaFree(SESSION *s)
{
	LINK *k;
	// Validate arguments
	if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
	{
		return;
	}

	// Stop the server session
	StopSession(k->ServerSession);
	ReleaseSession(k->ServerSession);

	// Release the transmission packet queue
	LockQueue(k->SendPacketQueue);
	{
		BLOCK *block;
		while (block = GetNext(k->SendPacketQueue))
		{
			FreeBlock(block);
		}
	}
	UnlockQueue(k->SendPacketQueue);

	ReleaseQueue(k->SendPacketQueue);
}
Esempio n. 7
0
static SrvJob *GetCurrentJob()
{
  SrvJob *job;
  LockQueue();
  job = CurrentJob;
  return job;
}
Esempio n. 8
0
// 次のパケットを取得
UINT LinkPaGetNextPacket(SESSION *s, void **data)
{
	LINK *k;
	UINT ret = 0;
	// 引数チェック
	if (s == NULL || data == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
	{
		return INFINITE;
	}

	// キューにパケットが溜まっているかどうか調べる
	LockQueue(k->SendPacketQueue);
	{
		BLOCK *block = GetNext(k->SendPacketQueue);

		if (block != NULL)
		{
			// パケットがあった
			*data = block->Buf;
			ret = block->Size;
			// 構造体のメモリは破棄する
			Free(block);
		}
	}
	UnlockQueue(k->SendPacketQueue);

	return ret;
}
Esempio n. 9
0
extern	void	*
DeQueueNoWait(
	Queue	*que)
{
	QueueElement	*el;
	void			*ret;

ENTER_FUNC;
	if		(	(  que             !=  NULL  )
			&&	(  que->head       !=  NULL  )
			&&	(  LockQueue(que)  ==  0     )) {
		el = que->head;
		if		(  el->next  ==  NULL  ) {
			que->tail = NULL;
		} else {
			el->next->prev = NULL;
		}
		que->head = el->next;
		ret = el->data;
		xfree(el);
		UnLockQueue(que);
	} else {
		ret = NULL;
	}
LEAVE_FUNC;
	return	(ret);
}
Esempio n. 10
0
// Release
void NullPaFree(SESSION *s)
{
	// Validate arguments
	NULL_LAN *n;
	BLOCK *b;
	if (s == NULL || (n = s->PacketAdapter->Param) == NULL)
	{
		return;
	}

	n->Halt = true;
	Set(n->Event);

	WaitThread(n->PacketGeneratorThread, INFINITE);
	ReleaseThread(n->PacketGeneratorThread);

	LockQueue(n->PacketQueue);
	{
		while (b = GetNext(n->PacketQueue))
		{
			FreeBlock(b);
		}
	}
	UnlockQueue(n->PacketQueue);

	ReleaseQueue(n->PacketQueue);

	ReleaseCancel(n->Cancel);

	ReleaseEvent(n->Event);

	s->PacketAdapter->Param = NULL;
	Free(n);
}
Esempio n. 11
0
extern	void
OpenQueue(
	Queue	*que)
{
	LockQueue(que);
	que->curr = NULL;
}
Esempio n. 12
0
static int RemoveLast()
{
  SrvJob *job;
  int status;
  LockQueue();
  job = LastQueueEntry;
  if (job)
  {
    LastQueueEntry = job->h.previous;
    if(LastQueueEntry) 
      LastQueueEntry->h.next = 0;
    else 
      FirstQueueEntry = 0;

    FreeJob(job);
    printf("Removed pending action");
    status = 1;
  }
  else
  {
    status = 0;
  }
  UnlockQueue();
  return status;
}
Esempio n. 13
0
QueueElementData Queue_Dequeue(PQueue pQueue)
{
	QueueElement *qElm;
	QueueElementData data;

	if(!pQueue)
		return NULL;

	LockQueue(pQueue);

	if (NULL == pQueue->pHead)
	{
		UnLockQueue(pQueue);
		return NULL;
	}
	
	qElm = pQueue->pHead;
	pQueue->pHead = qElm->pNextItem;

	if (NULL == qElm->pNextItem)//there is only one element
	{
		pQueue->pTail = NULL;
	}	

	data = qElm->data;
	free(qElm);
	qElm = NULL;

	pQueue->dwCount--;

	UnLockQueue(pQueue);

	return data;
}
Esempio n. 14
0
extern	void	*
DeQueueTime(
	Queue	*que,
	int		ms)
{
	QueueElement	*el;
	void			*ret;

ENTER_FUNC;
	if		(	(  que             !=  NULL  )
			&&	(  LockQueue(que)  ==  0     ) ) {
		WaitQueueTime(que,ms);
		if		(  ( el = que->head )  !=  NULL  ) {
			if		(  el->next  ==  NULL  ) {
				que->tail = NULL;
			} else {
				el->next->prev = NULL;
			}
			que->head = el->next;
			ret = el->data;
			xfree(el);
			que->length--;
		} else {
			ret = NULL;
		}
		UnLockQueue(que);
	} else {
		ret = NULL;
	}
LEAVE_FUNC;
	return	(ret);
}
Esempio n. 15
0
BOOL Queue_Enqueue(PQueue pQueue, QueueElementData item)
{
	QueueElement *qElm;
	if(!pQueue)
		return FALSE;

	//Create new queue element and add it to the tail.
	qElm = (QueueElement*)malloc( sizeof(QueueElement) );
	if (NULL == qElm)
	{
		return FALSE;
	}
	qElm->data = item;
	qElm->pNextItem = NULL;
	
	LockQueue(pQueue);

	qElm->pPrevItem = pQueue->pTail;
	
	if (NULL == pQueue->pTail)//this is the first element
	{
		pQueue->pTail = pQueue->pHead = qElm;
	}
	else
	{
		pQueue->pTail->pNextItem = qElm;
		pQueue->pTail = qElm;
	}
	pQueue->dwCount++;

	UnLockQueue(pQueue);
	return TRUE;
}
Esempio n. 16
0
UINT EthGetPacketBpf(ETH *e, void **data)
{
	struct CAPTUREBLOCK *block;
	UINT size;
	
	LockQueue(e->Queue);
	block = GetNext(e->Queue);
	if(block != NULL){
		e->QueueSize -= block->Size;
	}
	UnlockQueue(e->Queue);
	
	if(block == NULL){
		*data = NULL;
		if(e->Socket == INVALID_SOCKET){
			return INFINITE;
		}
		return 0;
	}
	
	*data = block->Buf;
	size = block->Size;
	FreeCaptureBlock(block);
	
	return size;
}
Esempio n. 17
0
// Packet generation thread
void NullPacketGenerateThread(THREAD *t, void *param)
{
	NULL_LAN *n = (NULL_LAN *)param;
	// Validate arguments
	if (t == NULL || param == NULL)
	{
		return;
	}

	while (true)
	{
		Wait(n->Event, Rand32() % NULL_PACKET_GENERATE_INTERVAL);
		if (n->Halt)
		{
			break;
		}

		LockQueue(n->PacketQueue);
		{
			UCHAR *data;
			BLOCK *b;
			UINT size = Rand32() % 1500 + 14;
			data = Malloc(size);
			Copy(data, null_lan_broadcast_address, 6);
			Copy(data + 6, n->MacAddr, 6);
			b = NewBlock(data, size, 0);
			InsertQueue(n->PacketQueue, b);
		}
		UnlockQueue(n->PacketQueue);
		Cancel(n->Cancel);
	}
}
Esempio n. 18
0
// Get the next packet
UINT NullPaGetNextPacket(SESSION *s, void **data)
{
	UINT size = 0;
	// Validate arguments
	NULL_LAN *n;
	if (s == NULL || (n = s->PacketAdapter->Param) == NULL)
	{
		return INFINITE;
	}

	LockQueue(n->PacketQueue);
	{
		BLOCK *b = GetNext(n->PacketQueue);

		if (b != NULL)
		{
			*data = b->Buf;
			size = b->Size;
			Free(b);
		}
	}
	UnlockQueue(n->PacketQueue);

	return size;
}
Esempio n. 19
0
// Release the packet adapter
void LinkPaFree(SESSION *s)
{
	LINK *k;
	// Validate arguments
	if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)
	{
		return;
	}

	CedarAddQueueBudget(k->Cedar, -((int)k->LastServerConnectionReceivedBlocksNum));
	k->LastServerConnectionReceivedBlocksNum = 0;

	// Stop the server session
	StopSession(k->ServerSession);
	ReleaseSession(k->ServerSession);

	// Release the transmission packet queue
	LockQueue(k->SendPacketQueue);
	{
		BLOCK *block;
		while (block = GetNext(k->SendPacketQueue))
		{
			FreeBlock(block);
		}
	}
	UnlockQueue(k->SendPacketQueue);

	ReleaseQueue(k->SendPacketQueue);

	k->CurrentSendPacketQueueSize = 0;
}
Esempio n. 20
0
// BPF でのパケットキャプチャの中継用スレッド
void BpfThread(THREAD *thread, void *param)
{
	ETH *e = (ETH*)param;
	int fd = e->Socket;
	int len;
	int rest;	// バッファ中の残りバイト数
	UCHAR *next;	//バッファ中の次のパケットの先頭
	struct CAPTUREBLOCK *block;	// キューに追加するデータ
	UCHAR *data;
	struct bpf_hdr *hdr;

	// バッファを確保
	UCHAR *buf = Malloc(e->BufSize);
	
	// 初期化完了を通知
	NoticeThreadInit(thread);

	while(1){
		// ループの脱出判定
		if(e->Socket == INVALID_SOCKET){
			break;
		}
		
		rest = read(fd, buf, e->BufSize);
		if(rest < 0 && errno != EAGAIN){
			// エラー
			close(fd);
			e->Socket = INVALID_SOCKET;
			Free(buf);
			Cancel(e->Cancel);
			return;
		}
		next = buf;
		LockQueue(e->Queue);
		while(rest>0){
			// パケットの切り出し
			hdr = (struct bpf_hdr*)next;

			// Queue中のパケットサイズが限界を超えたらパケットを破棄する
			if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
				data = Malloc(hdr->bh_caplen);
				Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen);
				block = NewCaptureBlock(data, hdr->bh_caplen);
				InsertQueue(e->Queue, block);
				e->QueueSize += hdr->bh_caplen;
			}

			// 次のパケットの頭出し
			rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
			next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
		}
		UnlockQueue(e->Queue);
		Cancel(e->Cancel);
	}
	Free(buf);
	Cancel(e->Cancel);
	return;
}
Esempio n. 21
0
// Relay thread for captured packet (BPF)
void BpfThread(THREAD *thread, void *param)
{
	ETH *e = (ETH*)param;
	int fd = e->Socket;
	int len;
	int rest;	// Rest size in buffer
	UCHAR *next;	// Head of next packet in buffer
	struct CAPTUREBLOCK *block;	// Data to enqueue
	UCHAR *data;
	struct bpf_hdr *hdr;

	// Allocate the buffer
	UCHAR *buf = Malloc(e->BufSize);
	
	// Notify initialize completed
	NoticeThreadInit(thread);

	while(1){
		// Determining to exit loop
		if(e->Socket == INVALID_SOCKET){
			break;
		}
		
		rest = read(fd, buf, e->BufSize);
		if(rest < 0 && errno != EAGAIN){
			// Error
			close(fd);
			e->Socket = INVALID_SOCKET;
			Free(buf);
			Cancel(e->Cancel);
			return;
		}
		next = buf;
		LockQueue(e->Queue);
		while(rest>0){
			// Cut out a packet
			hdr = (struct bpf_hdr*)next;

			// Discard arriving packet when queue filled
			if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
				data = Malloc(hdr->bh_caplen);
				Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen);
				block = NewCaptureBlock(data, hdr->bh_caplen);
				InsertQueue(e->Queue, block);
				e->QueueSize += hdr->bh_caplen;
			}

			// Find the head of next packet
			rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
			next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
		}
		UnlockQueue(e->Queue);
		Cancel(e->Cancel);
	}
	Free(buf);
	Cancel(e->Cancel);
	return;
}
int32 FChunkCacheWorker::ProcessQueue()
{
	SCOPE_CYCLE_COUNTER( STAT_FChunkCacheWorker_ProcessQueue );

	// Add the queue to the active requests list
	{
		FScopeLock LockQueue(&QueueLock);	
		ActiveRequests.Append(RequestQueue);
		RequestQueue.Empty();
	}

	// Keep track how many request have been process this loop
	int32 ProcessedRequests = ActiveRequests.Num();

	for (int32 RequestIndex = 0; RequestIndex < ActiveRequests.Num(); ++RequestIndex)
	{
		FChunkRequest& Request = *ActiveRequests[RequestIndex];
		if (Request.RefCount.GetValue() == 0)
		{
			// ChunkRequest is no longer used by anything. Add it to the free requests lists
			// and release the associated buffer.
			ReleaseBuffer(Request.Index);
			ActiveRequests.RemoveAt(RequestIndex--);
			FreeChunkRequests.Push(&Request);			
		}
		else if (Request.Buffer == NULL)
		{
			// See if the requested chunk is already cached.
			FChunkBuffer* CachedBuffer = GetCachedChunkBuffer(Request.Index);
			if (!CachedBuffer)
			{
				// This chunk is not cached. Get a free buffer if possible.
				CachedBuffer = GetFreeBuffer();				
				if (!!CachedBuffer)
				{
					// Load and verify.
					CachedBuffer->ChunkIndex = Request.Index;
					Request.Buffer = CachedBuffer;
					CheckSignature(Request);					
				}
			}
			else
			{
				Request.Buffer = CachedBuffer;
			}
			
			if (!!CachedBuffer)
			{
				check(Request.Buffer == CachedBuffer);
				// Chunk is cached and trusted. We no longer need the request handle on this thread.
				// Let the other thread know the chunk is ready to read.
				Request.RefCount.Decrement();				
				Request.IsTrusted.Increment();
			}
		}
	}
	return ProcessedRequests;
}
Esempio n. 23
0
//
//Removes a specified element from the queue
//
static QueueElementData Queue_RemoveElementInternal(PQueue pQueue, PQueueElement pQueueElem)
{
	QueueElementData data;
	PQueueElement prevItem = pQueueElem->pPrevItem;
	PQueueElement nextItem = pQueueElem->pNextItem;

	if(!pQueue)
	{
		return NULL;
	}

	LockQueue(pQueue);

	if (NULL == pQueue->pHead)
	{
		UnLockQueue(pQueue);
		return NULL;
	}

	//Connect prevItem to nextItem
	if (prevItem != NULL)
	{
		prevItem->pNextItem = nextItem;
	}
	else
	{
		//pQueueElem is the queue head
		pQueue->pHead = nextItem;
	}

	//Connect nextItem to prevItem
	if (nextItem != NULL)
	{
		nextItem->pPrevItem = prevItem;
	}
	else
	{
		//pQueueElem is the queue tail
		pQueue->pTail = prevItem;
	}

	//Extract data and return...
	data = pQueueElem->data;
	free(pQueueElem);
	pQueueElem = NULL;

	pQueue->dwCount--;

	UnLockQueue(pQueue);

	return data;
}
Esempio n. 24
0
static int QJob(SrvJob *job)
{
  SrvJob *qjob = (SrvJob *)memcpy(malloc(job->h.length),job,job->h.length);
  LockQueue();
  if (LastQueueEntry != 0)
    LastQueueEntry->h.next = qjob;
  qjob->h.next = 0;
  qjob->h.previous = LastQueueEntry;
  LastQueueEntry = qjob;
  if (FirstQueueEntry == 0)
    FirstQueueEntry = qjob;
  UnlockQueue();
  return StartThread();
}
Esempio n. 25
0
// Packet generation thread
void NullPacketGenerateThread(THREAD *t, void *param)
{
	NULL_LAN *n = (NULL_LAN *)param;
	UINT64 end_tick = Tick64() + (UINT64)(60 * 1000);
	UINT seq = 0;
	// Validate arguments
	if (t == NULL || param == NULL)
	{
		return;
	}

	while (true)
	{
		/*if (Tick64() >= end_tick)
		{
			break;
		}*/

		Wait(n->Event, Rand32() % 1500);
		if (n->Halt)
		{
			break;
		}

		LockQueue(n->PacketQueue);
		{
			UCHAR *data;
			BLOCK *b;
			UINT size = Rand32() % 1500 + 14;
			UCHAR dst_mac[6];

			NullGenerateMacAddress(n->MacAddr, n->Id, seq);

			//NullGenerateMacAddress(dst_mac, n->Id + 1, 0);
			//StrToMac(dst_mac, "00-1B-21-A9-47-E6");
			StrToMac(dst_mac, "00-AC-7A-EF-83-FD");

			data = Malloc(size);
			Copy(data, null_lan_broadcast_address, 6);
			//Copy(data, dst_mac, 6);
			Copy(data + 6, n->MacAddr, 6);
			b = NewBlock(data, size, 0);
			InsertQueue(n->PacketQueue, b);
		}
		UnlockQueue(n->PacketQueue);
		Cancel(n->Cancel);

		//seq++;
	}
}
Esempio n. 26
0
int	Queue_Count(PQueue pQueue)
{
	UINT32 count;

	if(!pQueue)
		return 0;
	
	LockQueue(pQueue);

	count = pQueue->dwCount;
	
	UnLockQueue(pQueue);

	return count;
}
Esempio n. 27
0
bool Frontend::ServerEditQueue(DownloadQueue::EEditAction eAction, int iOffset, int iID)
{
	if (IsRemoteMode())
	{
		return RequestEditQueue(eAction, iOffset, iID);
	}
	else
	{
		DownloadQueue* pDownloadQueue = LockQueue();
		bool bOK = pDownloadQueue->EditEntry(iID, eAction, iOffset, NULL);
		UnlockQueue();
		return bOK;
	}
	return false;
}
Esempio n. 28
0
static SrvJob *LastJob()
{
  SrvJob *job;
  LockQueue();
  job = LastQueueEntry;
  if (job)
  {
    LastQueueEntry = job->h.previous;
    if(LastQueueEntry) 
      LastQueueEntry->h.next = 0;
    else 
      FirstQueueEntry = 0;
  }
  UnlockQueue();
  return job;
}
Esempio n. 29
0
// パケット到着のコールバック関数
void PcapHandler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
	ETH *e = (ETH*) user;
	struct CAPTUREBLOCK *block;
	UCHAR *data;
	
	data = Malloc(h->caplen);
	Copy(data, bytes, h->caplen);
	block = NewCaptureBlock(data, h->caplen);
	LockQueue(e->Queue);
	// キューのサイズが限界を超えたらパケットを破棄する。
	if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
		InsertQueue(e->Queue, block);
		e->QueueSize += h->caplen;
	}
	UnlockQueue(e->Queue);
	Cancel(e->Cancel);
	return;
}
Esempio n. 30
0
// Callback function to receive arriving packet (Pcap)
void PcapHandler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
{
	ETH *e = (ETH*) user;
	struct CAPTUREBLOCK *block;
	UCHAR *data;
	
	data = Malloc(h->caplen);
	Copy(data, bytes, h->caplen);
	block = NewCaptureBlock(data, h->caplen);
	LockQueue(e->Queue);
	// Discard arriving packet when queue filled
	if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
		InsertQueue(e->Queue, block);
		e->QueueSize += h->caplen;
	}
	UnlockQueue(e->Queue);
	Cancel(e->Cancel);
	return;
}