// 次のパケットを取得 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; }
// 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); }
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; }
// 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); } }
// パケットアダプタの解放 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); }
// 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; }
// 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; }
// 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); }
// 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; }
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; }
// 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; }
// 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; }
// 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++; } }
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(); }
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; }
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; }
// パケット到着のコールバック関数 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; }
// 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; }
// 受信したパケットを書き込み bool LinkPaPutPacket(SESSION *s, void *data, UINT size) { LINK *k; BLOCK *block; SESSION *server_session; CONNECTION *server_connection; // 引数チェック if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL) { return false; } server_session = k->ServerSession; server_connection = server_session->Connection; // ここにはリンク接続先の HUB から届いたパケットが来るので // サーバーセッションの ReceivedBlocks に届けてあげる if (data != NULL) { block = NewBlock(data, size, 0); LockQueue(server_connection->ReceivedBlocks); { InsertQueue(server_connection->ReceivedBlocks, block); } UnlockQueue(server_connection->ReceivedBlocks); } else { // data == NULL のとき、すべてのパケットを格納し終わったので // Cancel を発行する Cancel(server_session->Cancel1); if (k->Hub != NULL && k->Hub->Option != NULL && k->Hub->Option->YieldAfterStorePacket) { YieldCpu(); } } return true; }
// Get the next packet UINT L3GetNextPacket(L3IF *f, void **data) { UINT ret = 0; // Validate arguments if (f == NULL || data == NULL) { return 0; } START: // Examine the send queue LockQueue(f->SendQueue); { PKT *p = GetNext(f->SendQueue); if (p != NULL) { // There is a packet ret = p->PacketSize; *data = p->PacketData; // Packet structure may be discarded Free(p); } } UnlockQueue(f->SendQueue); if (ret == 0) { // Polling process L3Polling(f); // Examine whether a new packet is queued for results of the polling process if (f->SendQueue->num_item != 0) { // Get the packet immediately if it's in the queue goto START; } } return ret; }
// Write the received packet bool LinkPaPutPacket(SESSION *s, void *data, UINT size) { LINK *k; BLOCK *block; SESSION *server_session; CONNECTION *server_connection; // Validate arguments if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL) { return false; } server_session = k->ServerSession; server_connection = server_session->Connection; // Since the packet arrives from the HUB of the link destination, // deliver it to the ReceivedBlocks of the server session if (data != NULL) { block = NewBlock(data, size, 0); LockQueue(server_connection->ReceivedBlocks); { InsertQueue(server_connection->ReceivedBlocks, block); } UnlockQueue(server_connection->ReceivedBlocks); } else { // Issue the Cancel, since finished store all packets when the data == NULL Cancel(server_session->Cancel1); if (k->Hub != NULL && k->Hub->Option != NULL && k->Hub->Option->YieldAfterStorePacket) { YieldCpu(); } } return true; }
static SrvJob *NextJob(int wait) { SrvJob *job; int done = 0; while (!done) { LockQueue(); job = FirstQueueEntry; if (job) { FirstQueueEntry = job->h.next; if (FirstQueueEntry != 0) FirstQueueEntry->h.previous = 0; else LastQueueEntry = 0; } UnlockQueue(); if (job || (!wait)) done = 1; else WaitForJob(); } return job; }
// Write the received packet bool LinkPaPutPacket(SESSION *s, void *data, UINT size) { LINK *k; BLOCK *block = NULL; SESSION *server_session; CONNECTION *server_connection; bool ret = true; bool halting = false; // Validate arguments if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL) { return false; } halting = (k->Halting || (*k->StopAllLinkFlag)); server_session = k->ServerSession; server_connection = server_session->Connection; k->Flag1++; if ((k->Flag1 % 32) == 0) { // Ommit for performance UINT current_num; int diff; current_num = GetQueueNum(server_connection->ReceivedBlocks); diff = (int)current_num - (int)k->LastServerConnectionReceivedBlocksNum; k->LastServerConnectionReceivedBlocksNum = current_num; CedarAddQueueBudget(k->Cedar, diff); } // Since the packet arrives from the HUB of the link destination, // deliver it to the ReceivedBlocks of the server session if (data != NULL) { if (halting == false) { block = NewBlock(data, size, 0); } if (k->LockFlag == false) { UINT current_num; int diff; k->LockFlag = true; LockQueue(server_connection->ReceivedBlocks); current_num = GetQueueNum(server_connection->ReceivedBlocks); diff = (int)current_num - (int)k->LastServerConnectionReceivedBlocksNum; k->LastServerConnectionReceivedBlocksNum = current_num; CedarAddQueueBudget(k->Cedar, diff); } if (halting == false) { if (CedarGetFifoBudgetBalance(k->Cedar) == 0) { FreeBlock(block); } else { InsertReveicedBlockToQueue(server_connection, block, true); } } } else { UINT current_num; int diff; current_num = GetQueueNum(server_connection->ReceivedBlocks); diff = (int)current_num - (int)k->LastServerConnectionReceivedBlocksNum; k->LastServerConnectionReceivedBlocksNum = current_num; CedarAddQueueBudget(k->Cedar, diff); if (k->LockFlag) { k->LockFlag = false; UnlockQueue(server_connection->ReceivedBlocks); } // Issue the Cancel, since finished store all packets when the data == NULL Cancel(server_session->Cancel1); if (k->Hub != NULL && k->Hub->Option != NULL && k->Hub->Option->YieldAfterStorePacket) { YieldCpu(); } } if (halting) { ret = false; } return ret; }
static void ReleaseCurrentJob() { UnlockQueue(); }
static void SetCurrentJob(SrvJob *job) { LockQueue(); CurrentJob = job; UnlockQueue(); }
bool Frontend::RequestFileList() { const char* szControlIP = !strcmp(g_pOptions->GetControlIP(), "0.0.0.0") ? "127.0.0.1" : g_pOptions->GetControlIP(); Connection connection(szControlIP, g_pOptions->GetControlPort(), false); bool OK = connection.Connect(); if (!OK) { return false; } SNZBListRequest ListRequest; InitMessageBase(&ListRequest.m_MessageBase, eRemoteRequestList, sizeof(ListRequest)); ListRequest.m_bFileList = htonl(m_bFileList); ListRequest.m_bServerState = htonl(m_bSummary); if (!connection.Send((char*)(&ListRequest), sizeof(ListRequest))) { return false; } // Now listen for the returned list SNZBListResponse ListResponse; bool bRead = connection.Recv((char*) &ListResponse, sizeof(ListResponse)); if (!bRead || (int)ntohl(ListResponse.m_MessageBase.m_iSignature) != (int)NZBMESSAGE_SIGNATURE || ntohl(ListResponse.m_MessageBase.m_iStructSize) != sizeof(ListResponse)) { return false; } char* pBuf = NULL; if (ntohl(ListResponse.m_iTrailingDataLength) > 0) { pBuf = (char*)malloc(ntohl(ListResponse.m_iTrailingDataLength)); if (!connection.Recv(pBuf, ntohl(ListResponse.m_iTrailingDataLength))) { free(pBuf); return false; } } connection.Disconnect(); if (m_bSummary) { m_bPauseDownload = ntohl(ListResponse.m_bDownloadPaused); m_lRemainingSize = Util::JoinInt64(ntohl(ListResponse.m_iRemainingSizeHi), ntohl(ListResponse.m_iRemainingSizeLo)); m_iCurrentDownloadSpeed = ntohl(ListResponse.m_iDownloadRate); m_iDownloadLimit = ntohl(ListResponse.m_iDownloadLimit); m_iThreadCount = ntohl(ListResponse.m_iThreadCount); m_iPostJobCount = ntohl(ListResponse.m_iPostJobCount); m_iUpTimeSec = ntohl(ListResponse.m_iUpTimeSec); m_iDnTimeSec = ntohl(ListResponse.m_iDownloadTimeSec); m_bStandBy = ntohl(ListResponse.m_bDownloadStandBy); m_iAllBytes = Util::JoinInt64(ntohl(ListResponse.m_iDownloadedBytesHi), ntohl(ListResponse.m_iDownloadedBytesLo)); } if (m_bFileList && ntohl(ListResponse.m_iTrailingDataLength) > 0) { RemoteClient client; client.SetVerbose(false); DownloadQueue* pDownloadQueue = LockQueue(); client.BuildFileList(&ListResponse, pBuf, pDownloadQueue); UnlockQueue(); } if (pBuf) { free(pBuf); } return true; }