void WUploadThread::timerEvent(QTimerEvent * /* e */) { if (IsInternalThreadRunning()) { if ((fLocallyQueued && !fForced) || fBlocked) { // Locally queued or blocked transfer don't need idle check restricting MessageRef nop(GetMessageFromPool(PR_COMMAND_NOOP)); if ( nop() ) { SendMessageToSessions(nop); } return; } // 1 minute maximum fIdles++; if (fIdles == 1) { MessageRef nop(GetMessageFromPool(PR_COMMAND_NOOP)); if ( nop() ) { SendMessageToSessions(nop); } } if (fIdles < 3) return; } // fall through ConnectTimer(); }
void PacketTunnelIOGateway :: HandleIncomingMessage(AbstractGatewayMessageReceiver & receiver, const ByteBufferRef & buf, const IPAddressAndPort & fromIAP) { if (_slaveGateway()) { DataIORef oldIO = _slaveGateway()->GetDataIO(); // save slave gateway's old state _fakeReceiveIO.SetBuffer(buf); (void) _fakeReceiveIO.Seek(0, SeekableDataIO::IO_SEEK_SET); _slaveGateway()->SetDataIO(DataIORef(&_fakeReceiveIO, false)); uint32 slaveBytesRead = 0; while(slaveBytesRead < buf()->GetNumBytes()) { _scratchReceiver = &receiver; _scratchReceiverArg = (void *) &fromIAP; int32 nextBytesRead = _slaveGateway()->DoInput(*this, buf()->GetNumBytes()-slaveBytesRead); if (nextBytesRead > 0) slaveBytesRead += nextBytesRead; else break; } _slaveGateway()->SetDataIO(oldIO); // restore slave gateway's old state _fakeReceiveIO.SetBuffer(ByteBufferRef()); } else { MessageRef inMsg = GetMessageFromPool(); if ((inMsg())&&(inMsg()->UnflattenFromByteBuffer(*buf()) == B_NO_ERROR)) receiver.CallMessageReceivedFromGateway(inMsg, (void *) &fromIAP); } }
static status_t ParseFileAux(StringTokenizer * optTok, FILE * fpIn, Message * optAddToMsg, Queue<String> * optAddToQueue, char * scratchBuf, uint32 bufSize, bool cs) { status_t ret = B_NO_ERROR; while(1) { const char * lineOfText = (optTok) ? optTok->GetNextToken() : fgets(scratchBuf, bufSize, fpIn); if (lineOfText == NULL) break; String checkForSection(lineOfText); checkForSection = optAddToMsg ? checkForSection.Trim() : ""; // sections are only supported for Messages, not Queue<String>'s if (cs == false) checkForSection = checkForSection.ToLowerCase(); if (((checkForSection == "begin")||(checkForSection.StartsWith("begin ")))&&(optAddToMsg)) // the check for (optAddToMsg) isn't really necessary, but it makes clang++ happy { checkForSection = checkForSection.Substring(6).Trim(); const int32 hashIdx = checkForSection.IndexOf('#'); if (hashIdx >= 0) checkForSection = checkForSection.Substring(0, hashIdx).Trim(); // Don't allow the parsing to fail just because the user specified a section name the same as a param name! uint32 tc; if ((optAddToMsg->GetInfo(checkForSection, &tc) == B_NO_ERROR)&&(tc != B_MESSAGE_TYPE)) (void) optAddToMsg->RemoveName(checkForSection); MessageRef subMsg = GetMessageFromPool(); if ((subMsg() == NULL)||(optAddToMsg->AddMessage(checkForSection, subMsg) != B_NO_ERROR)||(ParseFileAux(optTok, fpIn, subMsg(), optAddToQueue, scratchBuf, bufSize, cs) != B_NO_ERROR)) return B_ERROR; } else if ((checkForSection == "end")||(checkForSection.StartsWith("end "))) return B_NO_ERROR; else if (ParseArgsAux(lineOfText, optAddToMsg, optAddToQueue, cs) != B_NO_ERROR) { ret = B_ERROR; break; } } return ret; }
void PlainTextMessageIOGateway :: FlushInput(AbstractGatewayMessageReceiver & receiver) { if (_incomingText.HasChars()) { MessageRef inMsg = GetMessageFromPool(PR_COMMAND_TEXT_STRINGS); if ((inMsg())&&(inMsg()->AddString(PR_NAME_TEXT_LINE, _incomingText) == B_NO_ERROR)) { _incomingText.Clear(); receiver.CallMessageReceivedFromGateway(inMsg); } } }
void WUploadThread::SendRejectedNotification(bool direct) { MessageRef q(GetMessageFromPool(WTransfer::TransferNotifyRejected)); if (q()) { if (fTimeLeft != -1) q()->AddInt64("timeleft", fTimeLeft); if (direct || (fPort == 0)) { SendMessageToSessions(q); } else { QString node; if (fRemoteSessionID != QString::null) { node = "/*/"; node += fRemoteSessionID; } else { // use /<ip>/* instead of /*/<sessionid>, because session id isn't yet known at this point node = "/"; node += fStrRemoteIP; node += "/*"; } if ( (q()->AddString(PR_NAME_SESSION, "") == B_NO_ERROR) && (AddStringToMessage(q, PR_NAME_KEYS, node) == B_NO_ERROR) && (q()->AddInt32("port", (int32) fPort) == B_NO_ERROR) ) { gWin->SendRejectedNotification(q); } } } WUploadEvent *b = new WUploadEvent(WUploadEvent::FileBlocked); if (b) { if (fTimeLeft != -1) b->SetTime(fTimeLeft); SendReply(b); } }
void WUploadThread::SendQueuedNotification() { MessageRef q(GetMessageFromPool(WTransfer::TransferNotifyQueued)); if (q()) { SendMessageToSessions(q); WUploadEvent *qf = new WUploadEvent(WUploadEvent::FileQueued); if (qf) { SendReply(qf); } } }
MessageRef PlainTextMessageIOGateway :: AddIncomingText(const MessageRef & inMsg, const char * s) { MessageRef ret = inMsg; if (ret() == NULL) ret = GetMessageFromPool(PR_COMMAND_TEXT_STRINGS); if (ret()) { if (_incomingText.HasChars()) { (void) ret()->AddString(PR_NAME_TEXT_LINE, _incomingText.Append(s)); _incomingText.Clear(); } else (void) ret()->AddString(PR_NAME_TEXT_LINE, s); } return ret; }
// This proxy implementation receives raw data from the superclass and SLIP-decodes it, building up a Message full of decoded data to send to our own caller later. void SLIPFramedDataMessageIOGateway :: MessageReceivedFromGateway(const MessageRef & msg, void * /*userData*/) { const uint8 * buf; uint32 numBytes; for (int32 x=0; msg()->FindData(PR_NAME_DATA_CHUNKS, B_ANY_TYPE, x, (const void **) &buf, &numBytes) == B_NO_ERROR; x++) { for (uint32 i=0; i<numBytes; i++) { uint8 b = buf[i]; if (_lastReceivedCharWasEscape) { switch(b) { case SLIP_ESCAPE_END: AddPendingByte(SLIP_END); break; case SLIP_ESCAPE_ESC: AddPendingByte(SLIP_ESC); break; default: AddPendingByte(b); break; // protocol violation, but we'll just let the byte through since that is what the reference implementation does } _lastReceivedCharWasEscape = false; } else { switch(b) { case SLIP_END: if ((_pendingBuffer())&&(_pendingBuffer()->GetNumBytes() > 0)) { if (_pendingMessage() == NULL) _pendingMessage = GetMessageFromPool(msg()->what); if (_pendingMessage()) (void) _pendingMessage()->AddFlat(PR_NAME_DATA_CHUNKS, _pendingBuffer); _pendingBuffer.Reset(); } break; case SLIP_ESC: // do nothing break; default: AddPendingByte(b); break; } _lastReceivedCharWasEscape = (b==SLIP_ESC); } } } }
status_t AssembleBatchMessage(MessageRef & batchMsg, const MessageRef & newMsg) { if (batchMsg() == NULL) { batchMsg = newMsg; return B_NO_ERROR; } else if (batchMsg()->what == PR_COMMAND_BATCH) return batchMsg()->AddMessage(PR_NAME_KEYS, newMsg); else { MessageRef newBatchMsg = GetMessageFromPool(PR_COMMAND_BATCH); if ((newBatchMsg())&&(newBatchMsg()->AddMessage(PR_NAME_KEYS, batchMsg) == B_NO_ERROR)&&(newBatchMsg()->AddMessage(PR_NAME_KEYS, newMsg) == B_NO_ERROR)) { batchMsg = newBatchMsg; return B_NO_ERROR; } } return B_ERROR; }
status_t WUploadThread::SendMessageToSessions(const MessageRef & msgRef, const char * optDistPath) { if (fTunneled) { if ( (msgRef()->what == NetClient::ACCEPT_TUNNEL) || (msgRef()->what == NetClient::REJECT_TUNNEL) ) { // Send directly... QString to("/*/"); to += fRemoteSessionID; to += "/beshare"; AddStringToMessage(msgRef, PR_NAME_KEYS, to); msgRef()->AddString(PR_NAME_SESSION, ""); msgRef()->AddBool("upload", true); return static_cast<WUpload *>(fOwner)->netClient()->SendMessageToSessions(msgRef); } else { MessageRef up(GetMessageFromPool(NetClient::TUNNEL_MESSAGE)); if (up()) { QString to("/*/"); to += fRemoteSessionID; to += "/beshare"; AddStringToMessage(up, PR_NAME_KEYS, to); up()->AddString(PR_NAME_SESSION, ""); up()->AddMessage("message", msgRef); up()->AddBool("upload", true); up()->AddInt64("tunnel_id", hisID); return static_cast<WUpload *>(fOwner)->netClient()->SendMessageToSessions(up); } else return B_ERROR; } } else return qmtt->SendMessageToSessions(msgRef, optDistPath); }
MessageRef ReadZipFile(DataIO & readFrom, bool loadData) { TCHECKPOINT; static const int NAME_BUF_LEN = 8*1024; // names longer than 8KB are ridiculous anyway! char * nameBuf = newnothrow_array(char, NAME_BUF_LEN); if (nameBuf) { MessageRef ret = GetMessageFromPool(); if (ret()) { zlib_filefunc_def zdefs = { fopen_dataio_func, fread_dataio_func, fwrite_dataio_func, ftell_dataio_func, fseek_dataio_func, fclose_dataio_func, ferror_dataio_func, &readFrom }; zipFile zf = unzOpen2(NULL, &zdefs); if (zf != NULL) { if (ReadZipFileAux(zf, *ret(), nameBuf, NAME_BUF_LEN, loadData) != B_NO_ERROR) ret.Reset(); unzClose(zf); } else ret.Reset(); // failure! } delete [] nameBuf; return ret; } else WARN_OUT_OF_MEMORY; return MessageRef(); }
void WUploadThread::DoUpload() { PRINT("WUploadThread::DoUpload\n"); if (fShutdownFlag && *fShutdownFlag) // Do we need to interrupt? { ConnectTimer(); return; } // Still connected? if (!IsInternalThreadRunning()) { ConnectTimer(); return; } // Small files get to bypass queue if (IsLocallyQueued()) { if ( (fFile && (fFileSize >= gWin->fSettings->GetMinQueuedSize())) || IsManuallyQueued() ) { // not yet fForced = false; WUploadEvent *lq = new WUploadEvent(WUploadEvent::FileQueued); if (lq) { SendReply(lq); } return; } fForced = true; // Set this here to avoid duplicate call to DoUpload() } // Recheck if IP is ignored or not // if (gWin->IsIgnoredIP(fStrRemoteIP) && !IsBlocked()) { SetBlocked(true); } if (IsBlocked()) { WUploadEvent *wue = new WUploadEvent(WUploadEvent::FileBlocked); if (wue) { if (fTimeLeft != -1) wue->SetTime(fTimeLeft); SendReply(wue); } return; } if (fStartTime == 0) fStartTime = GetRunTime64(); if (fFile) { MessageRef uref(GetMessageFromPool(WTransfer::TransferFileData)); if (uref()) { // think about doing this in a dynamic way (depending on connection) double dpps = GetPacketSize() * 1024.0; uint32 bufferSize = lrint(dpps); ByteBufferRef buf = GetByteBufferFromPool(bufferSize); uint8 * scratchBuffer = buf()->GetBuffer(); if (scratchBuffer == NULL) { _nobuffer(); return; } int32 numBytes = 0; numBytes = fFile->ReadBlock32(scratchBuffer, bufferSize); if (numBytes > 0) { buf()->SetNumBytes(numBytes, true); // munge mode switch (fMungeMode) { case WTransfer::MungeModeNone: { uref()->AddInt32("mm", WTransfer::MungeModeNone); break; } case WTransfer::MungeModeXOR: { for (int32 x = 0; x < numBytes; x++) scratchBuffer[x] ^= 0xFF; uref()->AddInt32("mm", WTransfer::MungeModeXOR); break; } default: { break; } } if (uref()->AddFlat("data", buf) == B_OK) { // possibly do checksums here uref()->AddInt32("chk", CalculateFileChecksum(buf)); // a little paranoia, due to file-resumes not working.... (TCP should handle this BUT...) SendMessageToSessions(uref); // NOTE: RequestOutputQueuesDrainedNotification() can recurse, so we need to update the offset before // calling it! fCurrentOffset += numBytes; if (fTunneled) { SignalUpload(); } else { MessageRef drain(GetMessageFromPool()); if (drain()) qmtt->RequestOutputQueuesDrainedNotification(drain); } WUploadEvent *update = new WUploadEvent(WUploadEvent::FileDataSent); if (update) { update->SetOffset(fCurrentOffset); update->SetSize(fFileSize); update->SetSent(numBytes); if (fCurrentOffset >= fFileSize) { update->SetDone(true); // file done! update->SetFile(SimplifyPath(fFileUl)); if (gWin->fSettings->GetUploads()) { SystemEvent( gWin, tr("%1 has finished downloading %2.").arg( GetRemoteUser() ).arg( SimplifyPath(fFileUl) ) ); } } SendReply(update); } return; } else { _nobuffer(); return; } } if (numBytes <= 0) { NextFile(); SignalUpload(); return; } } } else { while (!fFile) { if (fUploads.GetNumItems() != 0) { // grab the ref and remove it from the list fUploads.RemoveHead(fCurrentRef); fFileUl = MakeUploadPath(fCurrentRef); #ifdef _DEBUG // <*****@*****.**> 20021023, 20030702 -- Add additional debug message WString wul(fFileUl); PRINT("WUploadThread::DoUpload: filePath = %S\n", wul.getBuffer()); #endif fFile = new WFile(); Q_CHECK_PTR(fFile); if (!fFile->Open(fFileUl, QIODevice::ReadOnly)) // probably doesn't exist { delete fFile; fFile = NULL; fCurFile++; continue; // onward } // got our file! fFileSize = fFile->Size(); fCurrentOffset = 0; // from the start if (fCurrentRef()->FindInt64("secret:offset", fCurrentOffset) == B_OK) { if (!fFile->Seek(fCurrentOffset)) // <*****@*****.**> 20021026 { fFile->Seek(0); // this can't fail :) (I hope) fCurrentOffset = 0; } } // copy the message in our current file ref MessageRef headRef = fCurrentRef.Clone(); if (headRef()) { headRef()->what = WTransfer::TransferFileHeader; headRef()->AddInt64("beshare:StartOffset", fCurrentOffset); SendMessageToSessions(headRef); } fCurFile++; // Reset statistics InitTransferRate(); InitTransferETA(); WUploadEvent *started = new WUploadEvent(WUploadEvent::FileStarted); if (started) { started->SetFile(SimplifyPath(fFileUl)); started->SetStart(fCurrentOffset); started->SetSize(fFileSize); #ifdef _DEBUG started->SetSession(fRemoteSessionID); #endif SendReply(started); } if (gWin->fSettings->GetUploads()) { SystemEvent( gWin, tr("%1 is downloading %2.").arg( GetRemoteUser() ).arg( SimplifyPath(fFileUl) ) ); } // nested call SignalUpload(); return; } else { PRINT("No more files!\n"); fWaitingForUploadToFinish = true; SetFinished(true); if (fTunneled) { _OutputQueuesDrained(); } else { MessageRef drain(GetMessageFromPool()); if (drain()) qmtt->RequestOutputQueuesDrainedNotification(drain); } break; } } } }
void WListThread::InternalThreadEntry() { Lock(); WinShareWindow * win = dynamic_cast<WinShareWindow *>(fOwner); // reset our shutdown flag if (fShutdownFlag) *fShutdownFlag = false; fFileScanThread->Lock(); int numShares = fFileScanThread->GetNumFiles(); if (win->Settings()->GetInfo()) { QString shares; switch (numShares) { case 0: shares = tr("No shared files."); break; case 1: shares = tr("Sharing 1 file."); break; default: shares = tr("Sharing %1 files.").arg(numShares); } SystemEvent(fOwner, shares); } fNet->SetFileCount(numShares); PRINT("Doing a scan of the returned files for uploading.\n"); int m = 0; MessageRef refScan(GetMessageFromPool(PR_COMMAND_SETDATA)); if (refScan()) { MessageRef mref; HashtableIterator<QString, QString> filesIter = fFileScanThread->GetSharedFilesIterator(HTIT_FLAG_NOREGISTER); while (filesIter.HasData()) { // stop iterating if we are waiting for file scan thread to finish if (fShutdownFlag && *fShutdownFlag) break; QString s = filesIter.GetKey(); filesIter++; MessageRef mref; if (fFileScanThread->FindFile(s, mref)) { MakeNodePath(s); uint32 enc = win->Settings()->GetEncoding(GetServerName(win->CurrentServer()), GetServerPort(win->CurrentServer())); String ms = (const char *) s.utf8(); // Use encoded file attributes? if (enc != 0) { MessageRef packed = DeflateMessage(mref, enc, true); if (packed()) { refScan()->AddMessage(ms, packed); m++; } else { // Failed to pack the message? refScan()->AddMessage(ms, mref); m++; } } else { refScan()->AddMessage(ms, mref); m++; } if (m == 20) { m = 0; fNet->SendMessageToSessions(refScan, 0); refScan = GetMessageFromPool(PR_COMMAND_SETDATA); } } } if (refScan()) { if (!refScan()->IsEmpty()) { fNet->SendMessageToSessions(refScan, 0); refScan.Reset(); } } } fFileScanThread->Unlock(); QCustomEvent *qce = new QCustomEvent(ListDone); if (qce) { QApplication::postEvent(fOwner, qce); } Unlock(); }