int freespace_private_sendAsync(FreespaceDeviceId id,
                                const uint8_t* message,
                                int length,
                                unsigned int timeoutMs,
                                freespace_sendCallback callback,
                                void* cookie) {

    struct FreespaceSendStruct* send;
    int retVal = 0;
    DWORD lastError = 0;

    retVal = prepareSend(id, &send, message, length);
    if (retVal != FREESPACE_SUCCESS) {
        return retVal;
    }
    send->callback_ = callback;
    send->cookie_ = cookie;
    send->timeoutMs_ = timeoutMs;

    // Send the message
    retVal = freespace_send_activate(send);
    if (retVal != FREESPACE_ERROR_IO) { // FAH: This looks wrong.
        return retVal;
    }
    return FREESPACE_SUCCESS;
}
Пример #2
0
/**
 * \bug  we need a way to guarantee that the write won't block when trying
 *       to send the ExitPacket on shutdown.
 */
void PacketStream::run() {
  int numPackets = 0;

  outQCtrl.acquire();
  while (!shutdown) {
    //Check the numpackets and call the feeder if needed.
    numPackets = (int)(outRel.size() + outUnrel.size());

    if (numPackets > 0) {
      //Trigger the onLowPackets event if needed
      onLowPackets(numPackets);

    } else {
      //Waiting loop for when there are no packets
      while (numPackets == 0 && !shutdown) {
        //Notify any threads waiting on waitToSendAll
        outQCtrl.broadcast();

        onLowPackets(numPackets);
        //Reevaluate numPackets because onLowPackets may add more packets.
        numPackets = (int)(outRel.size() + outUnrel.size());

        if (numPackets <= 0) {
          if (feederTimeout)
            outQCtrl.timedWait(feederTimeout);
          else
            outQCtrl.wait();
        }
      }
    }

    if (!shutdown) {
      //Check which queue woke us up.  Doing the check this way gives
      //absolute priority to reliable packets.
      bool reliable = !outRel.empty();
      assert(reliable || !outUnrel.empty());

      //Do throttled writes
      updateRates();
      if (outRemain > 0) {
        //Yes, this check will let us dip below 0, but overall we will make
        //up for it by waiting for it to go above 0 again.
        Buffer raw;
        prepareSend( ((reliable) ? outRel : outUnrel), raw);
        raw << PacketParser::END_OF_PACKET;
        outRemain -= raw.getPosition();

        //Release the mutex in case rawWrite blocks
        outQCtrl.release();
        if (owner.sockets.rawWrite(reliable, raw) != raw.getPosition()) {
          //We sleep here for a bit because we want to favor onExit if that is going to
          //happen.  Else this failure will occur.  Or we will favor a "real" error
          //more descriptive than a write error.
          Thread::sleep( 250 );
          owner.processError( LowLevelError(Error::Write) );
        }
        outQCtrl.acquire();
        
      } else {
        //Else we don't have any available bandwidth and we must wait!
        outQCtrl.release();
        Thread::sleep(TIME_STEP / 1000);
        outQCtrl.acquire();
      }
    }
  }
  outQCtrl.release();

  //We want to try to send the required ExitPacket, if possible, over the
  //reliable connection.
  //We need a good way to make sure this doesn't block though, but the
  //current solution here of assuming rawWrite won't block will have to do
  //for now.
  Buffer raw;
  ExitPacket temp;
  raw << temp << PacketParser::END_OF_PACKET;
  int ret = owner.sockets.rawWrite(true, raw);
  if (ret > raw.getPosition()) {
    gnedbgo1(4, "ExitPacket sent (%d).", ret);
  } else if ( ret > 0 ) {
    gnedbgo1(4, "ExitPackt not completely sent (%d).", ret);
  } else {
    gnedbgo1(4, "ExitPacket not sent (%d).", ret);
  }

  //Now that we have finished, release the PacketFeeder.
  LockCV lock( outQCtrl );
  feeder.reset();
  feederAllowed = false;
}
	char *sendBuffer(){
		prepareSend();
		return sndbuf;
	}
int freespace_private_send(FreespaceDeviceId id,
                           const uint8_t* report,
                           int length) {

    struct FreespaceSendStruct* send;
    int retVal = 0;
    DWORD lastError = 0;

    retVal = prepareSend(id, &send, report, length);
    if (retVal != FREESPACE_SUCCESS) {
        return retVal;
    }

    // Send the message
    retVal = freespace_send_activate(send);
    if (retVal != FREESPACE_ERROR_IO) {
        return retVal;
    }

    // Wait for the message to be sent
    lastError = WaitForSingleObject(send->overlapped_.hEvent, SEND_TIMEOUT);

    if (lastError != WAIT_OBJECT_0) {
        // timed out
        BOOL overlappedResult = GetOverlappedResult(send->interface_->handle_,
                                                    &send->overlapped_,
                                                    &send->numBytes_,
                                                    FALSE);

        // Abort any pending messages and return
        // WARNING: CancelIo will also affect READ!
        DEBUG_PRINTF("freespace_send: error on WaitForSingleObject = %d\n", lastError);
        CancelIo(send->interface_->handle_);
        send->interface_->readStatus_ = FALSE;

        if (overlappedResult) {
            send->rc_ = FREESPACE_ERROR_TIMEOUT;
        } else {
            send->rc_ = FREESPACE_ERROR_IO; //FREESPACE_OS_ERROR_BASE - lastError;
        }
    } else {
        // success
        BOOL overlappedResult = GetOverlappedResult(send->interface_->handle_,
                                                    &send->overlapped_,
                                                    &send->numBytes_,
                                                    TRUE);

        if (!overlappedResult) {
            DEBUG_PRINTF("freespace_send: error on GetOverlappedResult\n");
            send->rc_ = FREESPACE_ERROR_IO;
        } else if (send->numBytes_ != send->interface_->info_.outputReportByteLength_) {
            DEBUG_PRINTF("freespace_send: error on message size: %d != %d\n",
                         send->numBytes_, send->interface_->info_.outputReportByteLength_);
            send->rc_ = FREESPACE_ERROR_IO;
        } else {
            // successfully sent message
            send->rc_ = FREESPACE_SUCCESS;
        }
    }

    return finalizeSendStruct(send, FALSE);
}