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; }
/** * \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); }