// 受信したパケットを書き込み 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; }
// 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; }
// Folder enumeration void CfgEnumFolder(FOLDER *f, ENUM_FOLDER proc, void *param) { UINT i; // Validate arguments if (f == NULL || proc == NULL) { return; } for (i = 0;i < LIST_NUM(f->Folders);i++) { FOLDER *ff = LIST_DATA(f->Folders, i); if (proc(ff, param) == false) { break; } if ((i % 100) == 99) { YieldCpu(); } } }
// Output the folder contents (Recursive, binary) void CfgOutputFolderBin(BUF *b, FOLDER *f) { UINT i; // Validate arguments if (b == NULL || f == NULL) { return; } // Folder name WriteBufStr(b, f->Name); // The number of the subfolder WriteBufInt(b, LIST_NUM(f->Folders)); // Subfolder for (i = 0;i < LIST_NUM(f->Folders);i++) { FOLDER *sub = LIST_DATA(f->Folders, i); CfgOutputFolderBin(b, sub); if ((i % 100) == 99) { YieldCpu(); } } // The number of Items WriteBufInt(b, LIST_NUM(f->Items)); // Item for (i = 0;i < LIST_NUM(f->Items);i++) { char *utf8; UINT utf8_size; ITEM *t = LIST_DATA(f->Items, i); // Item Name WriteBufStr(b, t->Name); // Type WriteBufInt(b, t->Type); switch (t->Type) { case ITEM_TYPE_INT: // Integer WriteBufInt(b, *((UINT *)t->Buf)); break; case ITEM_TYPE_INT64: // 64-bit integer WriteBufInt64(b, *((UINT64 *)t->Buf)); break; case ITEM_TYPE_BYTE: // Data size WriteBufInt(b, t->size); // Data WriteBuf(b, t->Buf, t->size); break; case ITEM_TYPE_STRING: // String utf8_size = CalcUniToUtf8((wchar_t *)t->Buf) + 1; utf8 = ZeroMalloc(utf8_size); UniToUtf8(utf8, utf8_size, (wchar_t *)t->Buf); WriteBufInt(b, StrLen(utf8)); WriteBuf(b, utf8, StrLen(utf8)); Free(utf8); break; case ITEM_TYPE_BOOL: // Boolean type if (*((bool *)t->Buf) == false) { WriteBufInt(b, 0); } else { WriteBufInt(b, 1); } break; } } }
// Handle the communication of SSTP protocol bool ProcessSstpHttps(CEDAR *cedar, SOCK *s, SOCK_EVENT *se) { UINT tmp_size = 65536; UCHAR *tmp_buf; FIFO *recv_fifo; FIFO *send_fifo; SSTP_SERVER *sstp; bool ret = false; // Validate arguments if (cedar == NULL || s == NULL || se == NULL) { return false; } tmp_buf = Malloc(tmp_size); recv_fifo = NewFifo(); send_fifo = NewFifo(); sstp = NewSstpServer(cedar, &s->RemoteIP, s->RemotePort, &s->LocalIP, s->LocalPort, se, s->RemoteHostname, s->CipherName); while (true) { UINT r; bool is_disconnected = false; bool state_changed = false; // Receive data over SSL while (true) { r = Recv(s, tmp_buf, tmp_size, true); if (r == 0) { // SSL is disconnected is_disconnected = true; break; } else if (r == SOCK_LATER) { // Data is not received any more break; } else { // Queue the received data WriteFifo(recv_fifo, tmp_buf, r); state_changed = true; } } while (recv_fifo->size >= 4) { UCHAR *first4; UINT read_size = 0; bool ok = false; // Read 4 bytes from the beginning of the receive queue first4 = ((UCHAR *)recv_fifo->p) + recv_fifo->pos; if (first4[0] == SSTP_VERSION_1) { USHORT len = READ_USHORT(first4 + 2) & 0xFFF; if (len >= 4) { ok = true; if (recv_fifo->size >= len) { UCHAR *data; BLOCK *b; read_size = len; data = Malloc(read_size); ReadFifo(recv_fifo, data, read_size); b = NewBlock(data, read_size, 0); InsertQueue(sstp->RecvQueue, b); } } } if (read_size == 0) { break; } if (ok == false) { // Disconnect the connection since a bad packet received is_disconnected = true; break; } } // Process the timer interrupt SstpProcessInterrupt(sstp); if (sstp->Disconnected) { is_disconnected = true; } // Put the transmission data that SSTP module has generated into the transmission queue while (true) { BLOCK *b = GetNext(sstp->SendQueue); if (b == NULL) { break; } // When transmit a data packet, If there are packets of more than about // 2.5 MB in the transmission queue of the TCP, discard without transmission if (b->PriorityQoS || (send_fifo->size <= MAX_BUFFERING_PACKET_SIZE)) { WriteFifo(send_fifo, b->Buf, b->Size); } FreeBlock(b); } // Data is transmitted over SSL while (send_fifo->size != 0) { r = Send(s, ((UCHAR *)send_fifo->p) + send_fifo->pos, send_fifo->size, true); if (r == 0) { // SSL is disconnected is_disconnected = true; break; } else if (r == SOCK_LATER) { // Can not send any more break; } else { // Advance the transmission queue by the amount of the transmitted ReadFifo(send_fifo, NULL, r); state_changed = true; } } if (is_disconnected) { // Disconnected break; } // Wait for the next state change if (state_changed == false) { UINT select_time = SELECT_TIME; UINT r = GetNextIntervalForInterrupt(sstp->Interrupt); WaitSockEvent(se, MIN(r, select_time)); } } if (sstp != NULL && sstp->EstablishedCount >= 1) { ret = true; } FreeSstpServer(sstp); ReleaseFifo(recv_fifo); ReleaseFifo(send_fifo); Free(tmp_buf); YieldCpu(); Disconnect(s); return ret; }
// 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; }