// Read an entire pbuf from the NetworkTransaction bool NetworkTransaction::ReadBuffer(char *&buffer, unsigned int &len) { if (LostConnection() || pb == NULL) { return false; } if (inputPointer == pb->len) { // See if there is another pbuf in the chain if (inputPointer < pb->tot_len) { pb = pbuf_dechain(pb); if (pb == NULL) { return false; } inputPointer = 0; } else { return false; } } len = pb->len; buffer = static_cast<char *>(pb->payload); inputPointer += len; return true; }
// Webserver calls this to read bytes that have come in from the network. bool NetworkTransaction::Read(char& b) { if (LostConnection() || pb == NULL) { return false; } if (inputPointer == pb->len) { // See if there is another pbuf in the chain if (inputPointer < pb->tot_len) { pb = pbuf_dechain(pb); if (pb == NULL) { return false; } inputPointer = 0; } else { return false; } } b = ((const char*)pb->payload)[inputPointer++]; return true; }
bool RequestState::Read(char& b) { if (LostConnection() || pb == NULL) { return false; } while (inputPointer == pb->len) { // See if there is another pbuf in the chain if (inputPointer < pb->tot_len) { pbuf* next = pb->next; pb->next = NULL; pbuf_free(pb); pb = next; if (next == NULL) { return false; } inputPointer = 0; } else { return false; } } b = ((const char*)pb->payload)[inputPointer++]; return true; }
void NetworkTransaction::Write(const char* s, size_t len) { if (LostConnection() || status == disconnected) return; // Do we have a SendBuffer instance? Network *net = reprap.GetNetwork(); if (sendBuffer == NULL) { if (!net->AllocateSendBuffer(sendBuffer)) { // We cannot write because there are no more send buffers available. return; } } // Yes - retrieve the last send buffer from the chain. SendBuffer *lastSendBuffer = sendBuffer; while (lastSendBuffer->next != NULL) { lastSendBuffer = lastSendBuffer->next; } // Then try to store the whole string in multiple chunks if necessary. size_t bytesStored = 0, bytesToStore = min<size_t>(len, tcpOutputBufferSize - lastSendBuffer->bytesToWrite); do { // Fill up current SendBuffer memcpy(lastSendBuffer->tcpOutputBuffer + lastSendBuffer->bytesToWrite, s + bytesStored, bytesToStore); lastSendBuffer->bytesToWrite += bytesToStore; bytesStored += bytesToStore; bytesToStore = min<size_t>(tcpOutputBufferSize, len - bytesStored); // debugPrintf("%d of %d bytes stored, now storing %d bytes (%d bytes left in this chunk)\n", bytesStored, len, bytesToStore, tcpOutputBufferSize - currSendBuff->bytesToWrite); // Allocate another SendBuffer if we cannot store the whole string in the current one if (bytesToStore) { SendBuffer *newSendBuff; if (net->AllocateSendBuffer(newSendBuff)) { lastSendBuffer->next = newSendBuff; lastSendBuffer = newSendBuff; } else { // We cannot write because there are no more send buffers available. break; } } } while (bytesToStore); }
// Write formatted data to the output buffer void NetworkTransaction::Printf(const char* fmt, ...) { if (LostConnection() || status == disconnected) return; va_list p; va_start(p, fmt); char tempString[STRING_LENGTH]; int len = vsnprintf(tempString, STRING_LENGTH, fmt, p); va_end(p); Write(tempString, len); }
void NetworkTransaction::Write(char b) { if (LostConnection() || status == disconnected) return; if (sendBuffer == NULL) { if (reprap.GetNetwork()->AllocateSendBuffer(sendBuffer)) { sendBuffer->tcpOutputBuffer[0] = b; sendBuffer->bytesToWrite = 1; } else { // We cannot write because there are no more send buffers available. } } else { // Get the last SendBuffer in the chain SendBuffer *lastSendBuffer = sendBuffer; while (lastSendBuffer->next != NULL) { lastSendBuffer = lastSendBuffer->next; } // Check if there's enough space left if (tcpOutputBufferSize - lastSendBuffer->bytesToWrite > 0) { lastSendBuffer->tcpOutputBuffer[lastSendBuffer->bytesToWrite] = b; lastSendBuffer->bytesToWrite++; } // No, try to allocate another one instead and append it to the list else { SendBuffer *newSendBuffer; if (reprap.GetNetwork()->AllocateSendBuffer(newSendBuffer)) { lastSendBuffer->next = newSendBuffer; newSendBuffer->tcpOutputBuffer[0] = b; newSendBuffer->bytesToWrite = 1; } else { // We cannot write because there are no more send buffers available. } } } }
void RequestState::Write(char b) { if (LostConnection()) return; if (outputPointer >= ARRAY_SIZE(outputBuffer)) { reprap.GetPlatform()->Message(HOST_MESSAGE, "Network::Write(char b) - Output buffer overflow! \n"); return; } // Add the byte to the buffer outputBuffer[outputPointer] = b; outputPointer++; }
// Send exactly one TCP window of data or return true if we can free up this object bool NetworkTransaction::Send() { // Free up this transaction if we either lost our connection or are supposed to close it now if (LostConnection() || closeRequested) { if (fileBeingSent != NULL) { fileBeingSent->Close(); fileBeingSent = NULL; } Network *net = reprap.GetNetwork(); while (sendBuffer != NULL) { sendBuffer = net->ReleaseSendBuffer(sendBuffer); } if (!LostConnection()) { // debugPrintf("NetworkTransaction is closing connection cs=%08x\n", (unsigned int)cs); reprap.GetNetwork()->ConnectionClosed(cs, true); } if (closingDataPort) { if (ftp_pasv_pcb != NULL) { tcp_accept(ftp_pasv_pcb, NULL); tcp_close(ftp_pasv_pcb); ftp_pasv_pcb = NULL; } closingDataPort = false; } sendingTransaction = NULL; sentDataOutstanding = 0; return true; } // We're still waiting for data to be ACK'ed, so check timeouts here if (sentDataOutstanding) { if (!isnan(lastWriteTime)) { float timeNow = reprap.GetPlatform()->Time(); if (timeNow - lastWriteTime > writeTimeout) { reprap.GetPlatform()->Message(HOST_MESSAGE, "Network: Timing out connection cs=%08x\n", (unsigned int)cs); tcp_abort(cs->pcb); cs->pcb = NULL; } return false; } } else { sendingTransaction = NULL; } // See if we can fill up the TCP window with some data chunks from our SendBuffer instances uint16_t bytesBeingSent = 0, bytesLeftToSend = TCP_WND; while (sendBuffer != NULL && bytesLeftToSend >= sendBuffer->bytesToWrite) { memcpy(sendingWindow + bytesBeingSent, sendBuffer->tcpOutputBuffer, sendBuffer->bytesToWrite); bytesBeingSent += sendBuffer->bytesToWrite; bytesLeftToSend -= sendBuffer->bytesToWrite; sendBuffer = reprap.GetNetwork()->ReleaseSendBuffer(sendBuffer); } // We also intend to send a file, so check if we can fill up the TCP window if (sendBuffer == NULL) { int bytesRead; size_t bytesToRead; while (bytesLeftToSend && fileBeingSent != NULL) { bytesToRead = min<size_t>(256, bytesLeftToSend); // FIXME: doesn't work with higher block sizes bytesRead = fileBeingSent->Read(sendingWindow + bytesBeingSent, bytesToRead); if (bytesRead > 0) { bytesBeingSent += bytesRead; bytesLeftToSend = TCP_WND - bytesBeingSent; } if (bytesRead != bytesToRead) { fileBeingSent->Close(); fileBeingSent = NULL; } } } if (!bytesBeingSent) { // If we have no data to send and fileBeingSent is NULL, we can close the connection if (!cs->persistConnection && nextWrite == NULL) { Close(); return false; } // We want to send data from another transaction, so only free up this one return true; } else { // The TCP window has been filled up as much as possible, so send it now. There is no need to check // the available space in the SNDBUF queue, because we really write only one TCP window at once. tcp_sent(cs->pcb, conn_sent); err_t result = tcp_write(cs->pcb, sendingWindow, bytesBeingSent, 0); if (result != ERR_OK) // Final arg - 1 means make a copy { reprap.GetPlatform()->Message(HOST_MESSAGE, "Network: tcp_write returned error code %d, this should never happen!\n", result); tcp_abort(cs->pcb); cs->pcb = NULL; } else { sendingTransaction = this; sendingRetries = 0; sendingWindowSize = sentDataOutstanding = bytesBeingSent; lastWriteTime = reprap.GetPlatform()->Time(); tcp_output(cs->pcb); } } return false; }
// Send some data or close this connection if we can, returning true if we can free up this object bool RequestState::Send() { if (LostConnection()) { if (fileBeingSent != NULL) { fileBeingSent->Close(); fileBeingSent = NULL; } return true; } if (hs->SendInProgress()) { return false; } if (sentDataOutstanding != 0) { float timeNow = reprap.GetPlatform()->Time(); if (timeNow - lastWriteTime > writeTimeout) { debugPrintf("Timing out connection hs=%08x\n", (unsigned int)hs); HttpState *locHs = hs; // take a copy because our hs field is about to get cleared reprap.GetNetwork()->ConnectionClosing(locHs); tcp_pcb *pcb = locHs->pcb; tcp_arg(pcb, NULL); tcp_sent(pcb, NULL); tcp_recv(pcb, NULL); tcp_poll(pcb, NULL, 4); tcp_abort(pcb); mem_free(locHs); return false; // this RS will be freed next time round } } if (sentDataOutstanding >= ARRAY_SIZE(outputBuffer)/2) { return false; // don't send until at least half the output buffer is free } if (fileBeingSent != NULL) { unsigned int outputLimit = (sentDataOutstanding == 0) ? ARRAY_SIZE(outputBuffer) : min<unsigned int>(unsentPointer + ARRAY_SIZE(outputBuffer)/2, ARRAY_SIZE(outputBuffer)); while (outputPointer < outputLimit) { bool ok = fileBeingSent->Read(outputBuffer[outputPointer]); if (!ok) { fileBeingSent->Close(); fileBeingSent = NULL; break; } ++outputPointer; } } if (outputPointer == unsentPointer) { // We have no data to send. fileBeingSent must already be NULL here. if (!persistConnection && !closeRequested && nextWrite == NULL) { tcp_close(hs->pcb); closeRequested = true; // Don't release this RS yet, the write buffer may still be needed to do send retries return false; } if (sentDataOutstanding != 0) { return false; } // We've finished with this RS if (closeRequested) { // debugPrintf("Closing connection hs=%08x\n", (unsigned int)hs); HttpState *locHs = hs; // take a copy because our hs field is about to get cleared reprap.GetNetwork()->ConnectionClosing(locHs); tcp_pcb *pcb = locHs->pcb; tcp_arg(pcb, NULL); tcp_sent(pcb, NULL); tcp_recv(pcb, NULL); tcp_poll(pcb, NULL, 4); mem_free(locHs); } return true; } else { sentDataOutstanding += (outputPointer - unsentPointer); RepRapNetworkSendOutput(outputBuffer + unsentPointer, outputPointer - unsentPointer, hs); unsentPointer = (outputPointer == ARRAY_SIZE(outputBuffer)) ? 0 : outputPointer; outputPointer = unsentPointer; lastWriteTime = reprap.GetPlatform()->Time(); return false; } }
//#pragma optimize("", off) void VMVupManager::_HandleUdpPack() { s32 iSize = m_pUDPPackBuffer->GetSize(); if(iSize != 0) { UDP_PACKWrapper *poPacArray = new UDP_PACKWrapper[iSize]; m_pUDPPackBuffer->GetUDPData(poPacArray, iSize); for(s32 i = 0; i < iSize; ++i) { UDP_PACKWrapper *poPackWrapper = poPacArray + i; UDP_PACK* poPack = &(poPackWrapper->m_InnerData); switch(poPack->m_uiType) { case EPT_C2M_LostConnection: { LostConnection(poPackWrapper->m_ClientSocket); } break; case EPT_C2M_ClientRegister: { #ifndef USE_UDT_LIB Char cmd[VMCommand::kMaxCommandLength]; sprintf(cmd, "addvup %d %s %d", poPack->m_unValue.m_ClientRegisterParam.m_uiPassPort, poPackWrapper->m_SrcIPAddress.c_str(), poPack->m_unValue.m_ClientRegisterParam.m_uiPort); VMCommandCenter::GetPtr()->ExecuteFromString(cmd); sprintf(cmd, "updatevup %d -rs %d -tp %d", poPack->m_unValue.m_ClientRegisterParam.m_uiPassPort, poPack->m_unValue.m_ClientRegisterParam.m_uiStatus, poPack->m_unValue.m_ClientRegisterParam.m_uiTestPhase); VMCommandCenter::GetPtr()->ExecuteFromString(cmd); UDP_PACK pack; pack.m_uiType = EPT_M2C_ClientRegisterACK; m_pSendSocket->SetAddress(poPackWrapper->m_SrcIPAddress.c_str(), poPack->m_unValue.m_ClientRegisterParam.m_uiPort); m_pSendSocket->SendTo((const Char*)&pack, sizeof(UDP_PACK)); #else UDTSOCKET curSocket = poPackWrapper->m_ClientSocket; VMVup* pVup = FindVupBySocket(curSocket); if(pVup) { pVup->SetUniqueID(poPack->m_unValue.m_ClientRegisterParam.m_uiPassPort); pVup->SetStatus(poPack->m_unValue.m_ClientRegisterParam.m_uiStatus); pVup->SetTestPhase(poPack->m_unValue.m_ClientRegisterParam.m_uiTestPhase); LOG_INFO("get registered info from: %d(%s:%d)\n", pVup->GetUniqueID(), pVup->GetIPAddress(), pVup->GetPort()); Bool isOk = AddVup(pVup); UDP_PACK pack; pack.m_uiType = EPT_M2C_ClientRegisterACK; if(isOk) { pack.m_unValue.m_RegisterAckParam.m_uiHasSuccessed = true; s32 iRet = UDT::sendmsg(pVup->GetClientSocket(), (const Char*)&pack, sizeof(UDP_PACK)); if(iRet == UDT::ERROR) { LOG_INFO("[ERROR] sendmsg failed: %s\n", UDT::getlasterror().getErrorMessage()); } } else { pack.m_unValue.m_RegisterAckParam.m_uiHasSuccessed = false; s32 iRet = UDT::sendmsg(pVup->GetClientSocket(), (const Char*)&pack, sizeof(UDP_PACK)); if(iRet == UDT::ERROR) { LOG_INFO("[ERROR] sendmsg failed: %s\n", UDT::getlasterror().getErrorMessage()); } LOG_INFO("[ERROR] duplicate passport: %d\n", poPack->m_unValue.m_ClientRegisterParam.m_uiPassPort); } } else { LOG_INFO("[ERROR] cannot find vup in client list and retry: %d\n", poPack->m_unValue.m_ClientRegisterParam.m_uiPassPort); m_pUDPPackBuffer->InsertUDPData(*poPackWrapper); } #endif } break; case EPT_C2M_ReportClientStatus: { Char cmd[VMCommand::kMaxCommandLength]; sprintf(cmd, "updatevup %d -rs %d", poPack->m_unValue.m_ReportClientStatusParam.m_uiPassPort, poPack->m_unValue.m_ReportClientStatusParam.m_uiRunningStatus); VMCommandCenter::GetPtr()->ExecuteFromString(cmd); sprintf(cmd, "updatevup %d -tp %d", poPack->m_unValue.m_ReportClientStatusParam.m_uiPassPort, poPack->m_unValue.m_ReportClientStatusParam.m_uiTestPhase); VMCommandCenter::GetPtr()->ExecuteFromString(cmd); //LOG_INFO("get status %s, %s\n", VMVup::kStatus[poPack->m_unValue.m_ReportClientStatusParam.m_uiRunningStatus].GetName(), // VMVup::kTestPhase[poPack->m_unValue.m_ReportClientStatusParam.m_uiTestPhase].GetName()); } break; case EPT_C2M_ReachRDVPoint: { u16 uiRDVPoint = poPack->m_unValue.m_ReachRDVPointParam.m_uiRDVPointID; RDVPointListIterator itRDVPoint = m_poRDVList.find(uiRDVPoint); if(itRDVPoint == m_poRDVList.end()) { LOG_INFO("[RDV Point] new rdv point: %d\n", uiRDVPoint); RDVPointInfo info; info.m_uiID = uiRDVPoint; info.m_RunningInfo.m_bHasValidValue = true; info.m_RunningInfo.m_uiCurrentRunningID = uiRDVPoint; info.m_RunningInfo.m_fStartTime = GameEngine::GetGameEngine()->GetClockMod()->GetTotalElapsedSeconds(); info.m_RunningInfo.m_bIsGroupFull = false; itRDVPoint = m_poRDVList.insert(std::pair<RDVPointID, RDVPointInfo>(uiRDVPoint, info)).first; RDVPointInfo& pi = (*itRDVPoint).second; RDVPointRunningInfo& runningInfo = (*itRDVPoint).second.m_RunningInfo; RDVPointParameterListIterator itRDVPointParam = m_poRDVParam.find(Protocal::GetRDVPointID(Protocal::GetRDVPointMajor(uiRDVPoint), 0)); if(itRDVPointParam != m_poRDVParam.end()) { const RDVPointParameter& param = (*itRDVPointParam).second; runningInfo.m_GroupList.ReSize(param.m_iGroupNum); for(s32 i = 0; i < runningInfo.m_GroupList.Size(); ++i) { runningInfo.m_GroupList[i] = 0; } pi.m_uiExpectedNum = param.m_uiExpectedNum; pi.m_uiTimeOut = param.m_uiTimeOut; } else { runningInfo.m_GroupList.ReSize(1); runningInfo.m_GroupList[0] = 0; //TJQ: use default value pi.m_uiExpectedNum = 9999; pi.m_uiTimeOut = 10 * 60; } } else { RDVPointInfo& pi = (*itRDVPoint).second; D_CHECK(pi.m_RunningInfo.m_bHasValidValue); D_CHECK(pi.m_RunningInfo.m_uiCurrentRunningID == uiRDVPoint); //D_CHECK(pi.m_uiExpectedNum == poPack->m_unValue.m_ReachRDVPointParam.m_uiExpected); //D_CHECK(pi.m_uiTimeOut == poPack->m_unValue.m_ReachRDVPointParam.m_uiTimeout); } RDVPointRunningInfo& runningInfo = (*itRDVPoint).second.m_RunningInfo; RDVPointParameterListIterator itRDVPointParam = m_poRDVParam.find(Protocal::GetRDVPointID(Protocal::GetRDVPointMajor(uiRDVPoint), 0)); if(itRDVPointParam == m_poRDVParam.end()) { //use default VMVup* vup = FindVup(poPack->m_unValue.m_ReachRDVPointParam.m_uiPassPort); if(vup) { vup->SetGroup(0); vup->SetRDVPointID(uiRDVPoint); runningInfo.m_GroupList[0]++; LOG_INFO("[RDV Point] add vup %d to: R(%d, %d)G(0)[%d/-1]\n", poPack->m_unValue.m_ReachRDVPointParam.m_uiPassPort, Protocal::GetRDVPointMajor(uiRDVPoint), Protocal::GetRDVPointMinor(uiRDVPoint), runningInfo.m_GroupList[0]); runningInfo.m_ClientList.push_back(poPack->m_unValue.m_ReachRDVPointParam.m_uiPassPort); VMSummary::GroupUpdateParam guParam; guParam.m_AddorRemove = true; guParam.m_MaxNumberInGroup = -1; guParam.m_MyGroup = 0; guParam.m_VUPsPassport = poPack->m_unValue.m_ReachRDVPointParam.m_uiPassPort; VMSummary::GetPtr()->UpdateGroupInfo(Protocal::GetRDVPointMajor(uiRDVPoint), Protocal::GetRDVPointMinor(uiRDVPoint), 1, guParam); } } else { const RDVPointParameter& param = (*itRDVPointParam).second; VMVup* vup = FindVup(poPack->m_unValue.m_ReachRDVPointParam.m_uiPassPort); if(vup) { //Set RDV Point vup->SetRDVPointID(uiRDVPoint); //Set Group Bool bShouldFindAEmptyGroup = true; s32 iOriginalGroup = vup->GetGroup(); vup->SetGroup(-1); if(!runningInfo.m_bIsGroupFull) { if(iOriginalGroup >= 0 && iOriginalGroup < runningInfo.m_GroupList.Size()) { if(runningInfo.m_GroupList[iOriginalGroup] < param.m_iVUPNumInEachGroup) { runningInfo.m_GroupList[iOriginalGroup]++; vup->SetGroup(iOriginalGroup); bShouldFindAEmptyGroup = false; } } if(bShouldFindAEmptyGroup) { s32 idx = 0; for(idx = 0; idx < runningInfo.m_GroupList.Size(); ++idx) { if(runningInfo.m_GroupList[idx] < param.m_iVUPNumInEachGroup) { runningInfo.m_GroupList[idx]++; vup->SetGroup(idx); break; } } if(idx == runningInfo.m_GroupList.Size()) { runningInfo.m_bIsGroupFull = true; } } } if(vup->GetGroup() >= 0) { runningInfo.m_ClientList.push_back(poPack->m_unValue.m_ReachRDVPointParam.m_uiPassPort); VMSummary::GroupUpdateParam guParam; guParam.m_AddorRemove = true; guParam.m_MaxNumberInGroup = param.m_iVUPNumInEachGroup; guParam.m_MyGroup = vup->GetGroup(); guParam.m_VUPsPassport = poPack->m_unValue.m_ReachRDVPointParam.m_uiPassPort; VMSummary::GetPtr()->UpdateGroupInfo(Protocal::GetRDVPointMajor(uiRDVPoint), Protocal::GetRDVPointMinor(uiRDVPoint), param.m_iGroupNum, guParam); LOG_INFO("[RDV Point] add vup %d to: R(%d, %d)G(%d)[%d/%d]\n", poPack->m_unValue.m_ReachRDVPointParam.m_uiPassPort, Protocal::GetRDVPointMajor(uiRDVPoint), Protocal::GetRDVPointMinor(uiRDVPoint), vup->GetGroup(), runningInfo.m_GroupList[vup->GetGroup()], param.m_iVUPNumInEachGroup); } } } } break; } } delete[] poPacArray; } }