Пример #1
0
int32 PacketizedProxyDataIO :: Write(const void * buffer, uint32 size)
{
   if (size > _maxTransferUnit)
   {
      LogTime(MUSCLE_LOG_ERROR, "PacketizedProxyDataIO:  Error, tried to send packet with size " UINT32_FORMAT_SPEC ", max transfer unit is set to " UINT32_FORMAT_SPEC "\n", size, _maxTransferUnit);
      return -1;
   }

   // Only accept more data if we are done sending the data we already have buffered up
   bool tryAgainAfter = false;
   int32 ret = 0;
   if (HasBufferedOutput()) tryAgainAfter = true;
   else
   {
      // No data buffered?
      _outputBufferBytesSent = 0;

      if (_outputBuffer.SetNumBytes(sizeof(uint32)+size, false) != B_NO_ERROR) return 0;
      muscleCopyOut(_outputBuffer.GetBuffer(), B_HOST_TO_LENDIAN_INT32(size));
      memcpy(_outputBuffer.GetBuffer()+sizeof(uint32), buffer, size);
      ret = size;
   }

   if (WriteBufferedOutputAux() != B_NO_ERROR) return -1;

   return ((tryAgainAfter)&&(HasBufferedOutput() == false)) ? Write(buffer, size) : ret;
}
Пример #2
0
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;
}