Example #1
0
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
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #5
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;
}
Example #7
0
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;
}