/** * Mark the connection as connected */ void ConnectionImpl::setConnected() { // store connected state _state = state_connected; // we're going to call the handler, which can destruct the connection, // so we must monitor if the queue object is still valid after calling Monitor monitor(this); // inform handler _handler->onConnected(_parent); // empty the queue of messages while (monitor.valid() && !_queue.empty()) { // get the next message OutBuffer buffer(std::move(_queue.front())); // remove it from the queue _queue.pop(); // send it _handler->onData(_parent, buffer.data(), buffer.size()); } // leap out if object is dead if (!monitor.valid()) return; // if the close method was called before, and no channel is waiting // for an answer, we can now safely send out the close frame if (_closed && _state == state_connected && !waiting()) sendClose(); }
/** * Mark the connection as connected */ void ConnectionImpl::setConnected() { // store connected state _state = state_connected; // if the close method was called before, the frame was not // sent. append it to the end of the queue to make sure we // are correctly closed down. if (_closed && !sendClose()) return; // we're going to call the handler, which can destruct the connection, // so we must monitor if the queue object is still valid after calling Monitor monitor(this); // inform handler _handler->onConnected(_parent); // empty the queue of messages while (monitor.valid() && !_queue.empty()) { // get the next message OutBuffer buffer(std::move(_queue.front())); // remove it from the queue _queue.pop(); // send it _handler->onData(_parent, buffer.data(), buffer.size()); } }
int main( int argc, char **argv ) { int sendRate; rbudpSender_t *rbudpSender; if ( argc < 4 ) { printf( "Usage: sendfile <receiver> <sending rate (Kbps)> <MTU>\n" ); exit( 1 ); } sendRate = atoi( argv[2] ); // QUANTAnet_rbudpSender_c *mysender = new QUANTAnet_rbudpSender_c (38000); rbudpSender = malloc( sizeof( rbudpSender_t ) ); memset( rbudpSender, 0, sizeof( rbudpSender_t ) ); // the constructor QUANTAnet_rbudpSender_c( rbudpSender, SEND_PORT ); // mysender->init (argv[1]); initSender( rbudpSender, argv[1] ); QUANTAnet_rbudpBase_c( &rbudpSender->rbudpBase ); // mysender->sendfile (sendRate, atoi (argv[3])); rbSendfile( rbudpSender, sendRate, atoi( argv[3] ), ( char * ) 0 ); // mysender->close (); sendClose( rbudpSender ); return 1; }
/** * Parse the buffer into a recognized frame * * Every time that data comes in on the connection, you should call this method to parse * the incoming data, and let it handle by the AMQP library. This method returns the number * of bytes that were processed. * * If not all bytes could be processed because it only contained a partial frame, you should * call this same method later on when more data is available. The AMQP library does not do * any buffering, so it is up to the caller to ensure that the old data is also passed in that * later call. * * @param buffer buffer to decode * @return number of bytes that were processed */ uint64_t ConnectionImpl::parse(const Buffer &buffer) { // do not parse if already in an error state if (_state == state_closed) return 0; // number of bytes processed uint64_t processed = 0; // create a monitor object that checks if the connection still exists Monitor monitor(this); // keep looping until we have processed all bytes, and the monitor still // indicates that the connection is in a valid state while (processed < buffer.size() && monitor.valid()) { // prevent protocol exceptions try { // try to recognize the frame ReceivedFrame receivedFrame(ReducedBuffer(buffer, processed), _maxFrame); if (!receivedFrame.complete()) return processed; // process the frame receivedFrame.process(this); // number of bytes processed uint64_t bytes = receivedFrame.totalSize(); // add bytes processed += bytes; } catch (const ProtocolException &exception) { // something terrible happened on the protocol (like data out of range) reportError(exception.what()); // done return processed; } } // leap out if the connection object no longer exists if (!monitor.valid() || !_closed || _state != state_connected) return processed; // the close() function was called, but if the close frame was not yet sent // if there are no waiting channels, we can do that right now if (!waitingChannels()) sendClose(); // done return processed; }
/** * Close the connection * This will close all channels * @return bool */ bool ConnectionImpl::close() { // leap out if already closed or closing if (_closed) return false; // mark that the object is closed _closed = true; // if still busy with handshake, we delay closing for a while if (_state == state_handshake || _state == state_protocol) return true; // perform the close operation sendClose(); // done return true; }
/** * Close the connection * This will close all channels * @return bool */ bool ConnectionImpl::close() { // leap out if already closed or closing if (_closed) return false; // mark that the object is closed _closed = true; // after the send operation the object could be dead Monitor monitor(this); // number of channels that are waiting for an answer and that have further data int waiters = 0; // loop over all channels, and close them for (auto iter = _channels.begin(); iter != _channels.end(); iter++) { // close the channel iter->second->close(); // we could be dead now if (!monitor.valid()) return true; // is this channel waiting for an answer? if (iter->second->waiting()) waiters++; } // if still busy with handshake, we delay closing for a while if (waiters > 0 || _state != state_connected) return true; // perform the close frame sendClose(); // done return true; }
/** * Mark the connection as connected */ void ConnectionImpl::setConnected() { // store connected state _state = state_connected; // if the close operation was already called, we do that again now again // so that the actual messages to close down the connection and the channel // are appended to the queue if (_closed && !sendClose()) return; // we're going to call the handler, which can destruct the connection, // so we must monitor if the queue object is still valid after calling Monitor monitor(this); // inform handler _handler->onConnected(_parent); // leap out if the connection no longer exists if (!monitor.valid()) return; // empty the queue of messages while (!_queue.empty()) { // get the next message OutBuffer buffer(std::move(_queue.front())); // remove it from the queue _queue.pop(); // send it _handler->onData(_parent, buffer.data(), buffer.size()); // leap out if the connection was destructed if (!monitor.valid()) return; } }
bool I2CController::step(I2COp** result) { bool processing = true; *result = NULL; while (processing) { switch (state) { default: case I2C_STATE_ERROR: state = I2C_STATE_START; return true; case I2C_STATE_START_WAIT: case I2C_STATE_WRITE_ADDR_WAIT: case I2C_STATE_WRITE_DATA_WAIT: case I2C_STATE_READ_DATA_WAIT: if (intSet()) { state = (I2CState) (state + 1); } else { processing = false; } break; case I2C_STATE_START: if (pendingOps.getSize() > 0) { sendStart(); state = I2C_STATE_START_WAIT; } else { processing = false; } break; case I2C_STATE_START_RESPONSE: switch (TW_STATUS) { case TW_REP_START: case TW_START: state = I2C_STATE_WRITE_ADDR; break; case TW_MT_ARB_LOST: state = I2C_STATE_START; break; default: state = I2C_STATE_ERROR; break; } break; case I2C_STATE_WRITE_ADDR: writeByte( (pendingOps.peek()->addr << 1) | (pendingOps.peek()->write ? TW_WRITE : TW_READ)); state = I2C_STATE_WRITE_ADDR_WAIT; break; case I2C_STATE_WRITE_ADDR_RESPONSE: switch (TW_STATUS) { case TW_MT_SLA_ACK: case TW_MR_SLA_ACK: state = pendingOps.peek()->write ? I2C_STATE_WRITE_DATA : I2C_STATE_READ_DATA; break; case TW_MT_SLA_NACK: case TW_MR_SLA_NACK: case TW_MT_ARB_LOST: state = I2C_STATE_START; break; default: state = I2C_STATE_ERROR; break; } break; case I2C_STATE_WRITE_DATA: if (!pendingOps.getSize()) { state = I2C_STATE_START; } else if (!pendingOps.peek()->data.getSize()) { state = I2C_STATE_DATA_DONE; } else { writeByte(pendingOps.peek()->data.peek()); state = I2C_STATE_WRITE_DATA_WAIT; } break; case I2C_STATE_WRITE_DATA_RESPONSE: switch (TW_STATUS) { case TW_MT_DATA_ACK: pendingOps.peek()->data.dequeue(); state = I2C_STATE_WRITE_DATA; break; case TW_MT_DATA_NACK: case TW_MT_ARB_LOST: state = I2C_STATE_DATA_DONE; break; default: state = I2C_STATE_ERROR; break; } break; case I2C_STATE_READ_DATA: if (pendingOps.peek()->data.full()) { state = I2C_STATE_DATA_DONE; } else { requestByte( pendingOps.peek()->data.getSize() != pendingOps.peek()->data.getBufferSize() - 1); state = I2C_STATE_READ_DATA_WAIT; } break; case I2C_STATE_READ_DATA_RESPONSE: switch (TW_STATUS) { case TW_MR_DATA_ACK: pendingOps.peek()->data.enqueue(readByte()); state = I2C_STATE_READ_DATA; break; case TW_MR_DATA_NACK: pendingOps.peek()->data.enqueue(readByte()); state = I2C_STATE_DATA_DONE; break; default: state = I2C_STATE_ERROR; break; } break; case I2C_STATE_DATA_DONE: pendingOps.dequeue(result); case I2C_STATE_CLOSE: if (!pendingOps.getSize()) sendClose(); if (state == I2C_STATE_DATA_DONE) { state = I2C_STATE_START; return true; } else { state = I2C_STATE_START; break; } } } return false; }