int32 MultiDataIO :: Write(const void * buffer, uint32 size) { int64 newSeekPos = -1; // just to shut the compiler up uint32 maxWrittenBytes = 0; uint32 minWrittenBytes = MUSCLE_NO_LIMIT; for (int32 i=_childIOs.GetNumItems()-1; i>=0; i--) { int32 childRet = _childIOs[i]()->Write(buffer, muscleMin(size, minWrittenBytes)); if (childRet < 0) { if ((_absorbPartialErrors)&&(_childIOs.GetNumItems() > 1)) (void) _childIOs.RemoveItemAt(i); else return -1; } else { if ((uint32)childRet < minWrittenBytes) { minWrittenBytes = childRet; newSeekPos = _childIOs[i]()->GetPosition(); } maxWrittenBytes = muscleMax(maxWrittenBytes, (uint32)childRet); } } if (minWrittenBytes < maxWrittenBytes) { // Oh dear, some children wrote more bytes than others. To make their seek-positions equal again, // we are going to seek everybody to the seek-position of the child that wrote the fewest bytes. if (SeekAll(0, newSeekPos, IO_SEEK_CUR) != B_NO_ERROR) return -1; } return (maxWrittenBytes > 0) ? minWrittenBytes : 0; // the conditional is there in case minWrittenBytes is still MUSCLE_NO_LIMIT }
String UnparseArgs(const Queue<String> & args, uint32 startIdx, uint32 endIdx) { String ret; endIdx = muscleMin(endIdx, args.GetNumItems()); for (uint32 i=startIdx; i<endIdx; i++) { String subRet = args[i]; subRet.Replace("\"", "\\\""); if (subRet.IndexOf(' ') >= 0) subRet = subRet.Append("\"").Prepend("\""); if (ret.HasChars()) ret += ' '; ret += subRet; } return ret; }
static void WriteOctalASCII(uint8 * b, uint64 val, uint8 fieldSize) { // gotta pad out the file data to the nearest block boundary! char formatStr[16]; strcpy(formatStr, UINT64_FORMAT_SPEC" "); char * pi = strchr(formatStr, 'u'); if (pi) *pi = 'o'; // gotta use octal here! char tmp[256]; sprintf(tmp, formatStr, val); int numChars = muscleMin((int)fieldSize, ((int)(strlen(tmp)+1))); // include the NUL byte if possible uint8 * dStart = (b+fieldSize)-numChars; memcpy(dStart, tmp, numChars); memset(b, '0', dStart-b); // initial zeros }
int32 PlainTextMessageIOGateway :: DoOutputImplementation(uint32 maxBytes) { TCHECKPOINT; const Message * msg = _currentSendingMessage(); if (msg == NULL) { // try to get the next message from our queue (void) GetOutgoingMessageQueue().RemoveHead(_currentSendingMessage); msg = _currentSendingMessage(); _currentSendLineIndex = _currentSendOffset = -1; } if (msg) { if ((_currentSendOffset < 0)||(_currentSendOffset >= (int32)_currentSendText.Length())) { // Try to get the next line of text from our message if (msg->FindString(PR_NAME_TEXT_LINE, ++_currentSendLineIndex, _currentSendText) == B_NO_ERROR) { _currentSendOffset = 0; _currentSendText += _eolString; } else { _currentSendingMessage.Reset(); // no more text available? Go to the next message then. return DoOutputImplementation(maxBytes); } } if ((msg)&&(_currentSendOffset >= 0)&&(_currentSendOffset < (int32)_currentSendText.Length())) { // Send as much as we can of the current text line const char * bytes = _currentSendText.Cstr() + _currentSendOffset; int32 bytesWritten = GetDataIO()()->Write(bytes, muscleMin(_currentSendText.Length()-_currentSendOffset, maxBytes)); if (bytesWritten < 0) return -1; else if (bytesWritten > 0) { _currentSendOffset += bytesWritten; int32 subRet = DoOutputImplementation(maxBytes-bytesWritten); return (subRet >= 0) ? subRet+bytesWritten : -1; } } } return 0; }
int32 PacketizedProxyDataIO :: Read(void * buffer, uint32 size) { int32 ret = 0; if (_inputBufferSizeBytesRead < sizeof(uint32)) { uint8 * ip = (uint8 *) &_inputBufferSize; const int32 numSizeBytesRead = ProxyDataIO::Read(&ip[_inputBufferSizeBytesRead], sizeof(uint32)-_inputBufferSizeBytesRead); if (numSizeBytesRead < 0) return -1; _inputBufferSizeBytesRead += numSizeBytesRead; if (_inputBufferSizeBytesRead == sizeof(uint32)) { _inputBufferSize = B_LENDIAN_TO_HOST_INT32(_inputBufferSize); if (_inputBufferSize > _maxTransferUnit) { LogTime(MUSCLE_LOG_ERROR, "PacketizedProxyDataIO: Error, incoming packet with size " UINT32_FORMAT_SPEC ", max transfer unit is set to " UINT32_FORMAT_SPEC "\n", _inputBufferSize, _maxTransferUnit); return -1; } if (_inputBuffer.SetNumBytes(_inputBufferSize, false) != B_NO_ERROR) return -1; _inputBufferBytesRead = 0; // Special case for empty packets if (_inputBufferSize == 0) _inputBufferSizeBytesRead = 0; } } const uint32 inBufSize = _inputBuffer.GetNumBytes(); if ((_inputBufferSizeBytesRead == sizeof(uint32))&&(_inputBufferBytesRead < inBufSize)) { const int32 numBytesRead = ProxyDataIO::Read(_inputBuffer.GetBuffer()+_inputBufferBytesRead, inBufSize-_inputBufferBytesRead); if (numBytesRead < 0) return -1; _inputBufferBytesRead += numBytesRead; if (_inputBufferBytesRead == inBufSize) { const uint32 copyBytes = muscleMin(size, inBufSize); if (size < inBufSize) LogTime(MUSCLE_LOG_WARNING, "PacketizedProxyDataIO: Truncating incoming packet (" UINT32_FORMAT_SPEC " bytes available, only " UINT32_FORMAT_SPEC " bytes in user buffer)\n", inBufSize, size); memcpy(buffer, _inputBuffer.GetBuffer(), copyBytes); ret = copyBytes; _inputBufferSizeBytesRead = _inputBufferBytesRead = 0; _inputBuffer.Clear(inBufSize>(64*1024)); // free up memory after a large packet recv } } return ret; }
int32 PlainTextMessageIOGateway :: DoInputImplementation(AbstractGatewayMessageReceiver & receiver, uint32 maxBytes) { TCHECKPOINT; int32 ret = 0; const int tempBufSize = 2048; char buf[tempBufSize]; int32 bytesRead = GetDataIO()()->Read(buf, muscleMin(maxBytes, (uint32)(sizeof(buf)-1))); if (bytesRead < 0) { FlushInput(receiver); return -1; } if (bytesRead > 0) { uint32 filteredBytesRead = bytesRead; FilterInputBuffer(buf, filteredBytesRead, sizeof(buf)-1); ret += filteredBytesRead; buf[filteredBytesRead] = '\0'; MessageRef inMsg; // demand-allocated int32 beginAt = 0; for (uint32 i=0; i<filteredBytesRead; i++) { char nextChar = buf[i]; if ((nextChar == '\r')||(nextChar == '\n')) { buf[i] = '\0'; // terminate the string here if ((nextChar == '\r')||(_prevCharWasCarriageReturn == false)) inMsg = AddIncomingText(inMsg, &buf[beginAt]); beginAt = i+1; } _prevCharWasCarriageReturn = (nextChar == '\r'); } if (beginAt < (int32)filteredBytesRead) { if (_flushPartialIncomingLines) inMsg = AddIncomingText(inMsg, &buf[beginAt]); else _incomingText += &buf[beginAt]; } if (inMsg()) receiver.CallMessageReceivedFromGateway(inMsg); } return ret; }
String CleanupDNSLabel(const String & s, const String & optAdditionalAllowedChars) { const uint32 len = muscleMin(s.Length(), (uint32)63); // DNS spec says maximum 63 chars per label! String ret; if (ret.Prealloc(len) != B_NO_ERROR) return ret; const char * p = s(); for (uint32 i=0; i<len; i++) { const char c = p[i]; switch(c) { case '\'': case '\"': case '(': case ')': case '[': case ']': case '{': case '}': // do nothing -- we will omit delimiters break; default: if ((muscleInRange(c, '0', '9'))||(muscleInRange(c, 'A', 'Z'))||(muscleInRange(c, 'a', 'z'))||(optAdditionalAllowedChars.Contains(c))) ret += c; else if ((ret.HasChars())&&(ret.EndsWith('-') == false)) ret += '-'; break; } } while(ret.EndsWith('-')) ret -= '-'; // remove any trailing dashes return ret; }
int32 PacketTunnelIOGateway :: DoOutputImplementation(uint32 maxBytes) { if (_outputPacketBuffer.SetNumBytes(_maxTransferUnit, false) != B_NO_ERROR) return -1; uint32 totalBytesWritten = 0; bool firstTime = true; while((totalBytesWritten < maxBytes)&&((firstTime)||(IsSuggestedTimeSliceExpired() == false))) { firstTime = false; // Step 1: Add as much data to our output packet buffer as we can fit into it while((_outputPacketSize+FRAGMENT_HEADER_SIZE < _maxTransferUnit)&&(HasBytesToOutput())) { // Demand-create the next send-buffer if (_currentOutputBuffer() == NULL) { MessageRef msg; if (GetOutgoingMessageQueue().RemoveHead(msg) == B_NO_ERROR) { _currentOutputBufferOffset = 0; _currentOutputBuffer.Reset(); if (_slaveGateway()) { DataIORef oldIO = _slaveGateway()->GetDataIO(); // save slave gateway's old state // Get the slave gateway to generate its output into our ByteBuffer _fakeSendBuffer.SetNumBytes(0, false); _fakeSendIO.Seek(0, SeekableDataIO::IO_SEEK_SET); _slaveGateway()->SetDataIO(DataIORef(&_fakeSendIO, false)); _slaveGateway()->AddOutgoingMessage(msg); while(_slaveGateway()->DoOutput() > 0) {/* empty */} _slaveGateway()->SetDataIO(oldIO); // restore slave gateway's old state _currentOutputBuffer.SetRef(&_fakeSendBuffer, false); } else if (_fakeSendBuffer.SetNumBytes(msg()->FlattenedSize(), false) == B_NO_ERROR) { // Default algorithm: Just flatten the Message into the buffer msg()->Flatten(_fakeSendBuffer.GetBuffer()); _currentOutputBuffer.SetRef(&_fakeSendBuffer, false); } } } if (_currentOutputBuffer() == NULL) break; // oops, out of mem? uint32 sbSize = _currentOutputBuffer()->GetNumBytes(); uint32 dataBytesToSend = muscleMin(_maxTransferUnit-(_outputPacketSize+FRAGMENT_HEADER_SIZE), sbSize-_currentOutputBufferOffset); uint8 * p = _outputPacketBuffer.GetBuffer()+_outputPacketSize; muscleCopyOut(&p[0*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(_magic)); // a well-known magic number, for sanity checking muscleCopyOut(&p[1*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(_sexID)); // source exclusion ID muscleCopyOut(&p[2*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(_sendMessageIDCounter)); // message ID tag so the receiver can track what belongs where muscleCopyOut(&p[3*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(_currentOutputBufferOffset)); // start offset (within its message) for this sub-chunk muscleCopyOut(&p[4*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(dataBytesToSend)); // size of this sub-chunk muscleCopyOut(&p[5*sizeof(uint32)], B_HOST_TO_LENDIAN_INT32(sbSize)); // total size of this message //printf("CREATING PACKET magic=" UINT32_FORMAT_SPEC " msgID=" UINT32_FORMAT_SPEC " offset=" UINT32_FORMAT_SPEC " chunkSize=" UINT32_FORMAT_SPEC " totalSize=" UINT32_FORMAT_SPEC "\n", _magic, _sendMessageIDCounter, _currentOutputBufferOffset, dataBytesToSend, sbSize); memcpy(p+FRAGMENT_HEADER_SIZE, _currentOutputBuffer()->GetBuffer()+_currentOutputBufferOffset, dataBytesToSend); _outputPacketSize += (FRAGMENT_HEADER_SIZE+dataBytesToSend); _currentOutputBufferOffset += dataBytesToSend; if (_currentOutputBufferOffset == sbSize) { _currentOutputBuffer.Reset(); _fakeSendBuffer.Clear(_fakeSendBuffer.GetNumBytes() > MAX_CACHE_SIZE); // don't keep too much memory around! _sendMessageIDCounter++; } } // Step 2: If we have a non-empty packet to send, send it! if (_outputPacketSize > 0) { // If bytesWritten is set to zero, we just hold this buffer until our next call. int32 bytesWritten = GetDataIO()()->Write(_outputPacketBuffer.GetBuffer(), _outputPacketSize); //printf("WROTE " INT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " bytes %s\n", bytesWritten, _outputPacketSize, (bytesWritten==(int32)_outputPacketSize)?"":"******** SHORT ***********"); if (bytesWritten > 0) { if (bytesWritten != (int32)_outputPacketSize) LogTime(MUSCLE_LOG_ERROR, "PacketTunnelIOGateway::DoOutput(): Short write! (" INT32_FORMAT_SPEC "/" UINT32_FORMAT_SPEC " bytes)\n", bytesWritten, _outputPacketSize); _outputPacketBuffer.Clear(); _outputPacketSize = 0; totalBytesWritten += bytesWritten; } else if (bytesWritten == 0) break; // no more space to write, for now else return -1; } else break; // nothing more to do! } return totalBytesWritten; }
uint64 AbstractReflectSession :: GetPulseTime(const PulseArgs &) { return muscleMin(IsThisSessionScheduledForPostSleepReconnect()?MUSCLE_TIME_NEVER:_reconnectTime, _asyncConnectTimeoutTime); }
int32 PlainTextMessageIOGateway :: DoInputImplementation(AbstractGatewayMessageReceiver & receiver, uint32 maxBytes) { TCHECKPOINT; int32 ret = 0; const int tempBufSize = 2048; char buf[tempBufSize]; const uint32 mtuSize = GetMaximumPacketSize(); if (mtuSize > 0) { // Packet-IO implementation char * pbuf = buf; int pbufSize = tempBufSize; ByteBufferRef bigBuf; if (mtuSize > tempBufSize) { // Just in case our MTU size is too big for our on-stack buffer bigBuf = GetByteBufferFromPool(mtuSize); if (bigBuf()) { pbuf = (char *) bigBuf()->GetBuffer(); pbufSize = bigBuf()->GetNumBytes(); } } while(true) { IPAddressAndPort sourceIAP; const int32 bytesRead = GetPacketDataIO()->ReadFrom(pbuf, muscleMin(maxBytes, (uint32)(pbufSize-1)), sourceIAP); if (bytesRead < 0) return (ret > 0) ? ret : -1; else if (bytesRead > 0) { uint32 filteredBytesRead = bytesRead; FilterInputBuffer(pbuf, filteredBytesRead, pbufSize-1); ret += filteredBytesRead; pbuf[filteredBytesRead] = '\0'; bool prevCharWasCarriageReturn = false; // deliberately a local var, since UDP packets should be independent of each other MessageRef inMsg; // demand-allocated int32 beginAt = 0; for (uint32 i=0; i<filteredBytesRead; i++) { char nextChar = pbuf[i]; if ((nextChar == '\r')||(nextChar == '\n')) { pbuf[i] = '\0'; // terminate the string here if ((nextChar == '\r')||(prevCharWasCarriageReturn == false)) inMsg = AddIncomingText(inMsg, &pbuf[beginAt]); beginAt = i+1; } prevCharWasCarriageReturn = (nextChar == '\r'); } if (beginAt < (int32)filteredBytesRead) inMsg = AddIncomingText(inMsg, &pbuf[beginAt]); if (inMsg()) { (void) inMsg()->AddFlat(PR_NAME_PACKET_REMOTE_LOCATION, sourceIAP); receiver.CallMessageReceivedFromGateway(inMsg); inMsg.Reset(); } ret += bytesRead; } else return ret; } } else { // Stream-IO implementation const int32 bytesRead = GetDataIO()()->Read(buf, muscleMin(maxBytes, (uint32)(sizeof(buf)-1))); if (bytesRead < 0) { FlushInput(receiver); return -1; } if (bytesRead > 0) { uint32 filteredBytesRead = bytesRead; FilterInputBuffer(buf, filteredBytesRead, sizeof(buf)-1); ret += filteredBytesRead; buf[filteredBytesRead] = '\0'; MessageRef inMsg; // demand-allocated int32 beginAt = 0; for (uint32 i=0; i<filteredBytesRead; i++) { char nextChar = buf[i]; if ((nextChar == '\r')||(nextChar == '\n')) { buf[i] = '\0'; // terminate the string here if ((nextChar == '\r')||(_prevCharWasCarriageReturn == false)) inMsg = AddIncomingText(inMsg, &buf[beginAt]); beginAt = i+1; } _prevCharWasCarriageReturn = (nextChar == '\r'); } if (beginAt < (int32)filteredBytesRead) { if (_flushPartialIncomingLines) inMsg = AddIncomingText(inMsg, &buf[beginAt]); else _incomingText += &buf[beginAt]; } if (inMsg()) receiver.CallMessageReceivedFromGateway(inMsg); } } return ret; }