bool LocalForwarder::tryForward(Sirikata::Protocol::Object::ObjectMessage* msg) { ObjectConnection* conn = NULL; { boost::lock_guard<boost::mutex> lock(mMutex); // Destination connection must exist and be enabled ObjectConnectionMap::iterator it = mActiveConnections.find(msg->dest_object()); if (it == mActiveConnections.end()) return false; conn = it->second; // FIXME we can't sanity check here because we use this after // receiving from another space server (in which case we won't // have the source object...). // We only sanity check the source object when we're sure we're going to be able to // ship it. //ObjectConnectionMap::iterator src_it = mActiveConnections.find(msg->source_object()); //if (src_it == mActiveConnections.end()) // return false; } assert(conn != NULL); // Finally, with all checks done, we can commit to doing local routing TIMESTAMP_START(tstamp, msg); TIMESTAMP_END(tstamp, Trace::FORWARDED_LOCALLY); // If a stop was requested, don't try to forward. if (mContext->stopped()) return false; bool send_success = conn->send(msg); if (!send_success) { TIMESTAMP_END(tstamp, Trace::DROPPED_AT_FORWARDED_LOCALLY); TRACE_DROP(DROPPED_AT_FORWARDED_LOCALLY); // FIXME do anything on failure? delete msg; } // At this point we've handled it, regardless of send's success return true; }
void SpaceNodeConnection::handleRead(const Chunk& chunk, const Sirikata::Network::Stream::PauseReceiveCallback& pause) { mHandleReadStage->started(); // Parse ObjectMessage* msg = new ObjectMessage(); bool parse_success = msg->ParseFromArray(&(*chunk.begin()), chunk.size()); if (!parse_success) { LOG_INVALID_MESSAGE(session, error, chunk); delete msg; return; } TIMESTAMP_START(tstamp, msg); // Mark as received TIMESTAMP_END(tstamp, Trace::OH_NET_RECEIVED); // NOTE: We can't record drops here or we incur a lot of overhead in parsing... // Session messages need to be reliable, we force them through bool session_msg = (msg->dest_port() == OBJECT_PORT_SESSION); bool pushed = receive_queue.push(msg, session_msg); if (pushed) { // handleConnectionRead() could be called from any thread/strand. Everything that is not // thread safe that could result from a new message needs to happen in the main strand, // so just post the whole handler there. if (receive_queue.wentNonEmpty()) mReceiveCB(this); } else { TIMESTAMP_END(tstamp, Trace::OH_DROPPED_AT_RECEIVE_QUEUE); TRACE_DROP(OH_DROPPED_AT_RECEIVE_QUEUE); delete msg; } mHandleReadStage->finished(); // No matter what, we've "handled" the data, either for real or by dropping. }
bool SpaceNodeConnection::push(const ObjectMessage& msg) { TIMESTAMP_START(tstamp, (&msg)); std::string data; msg.serialize(&data); // Try to push to the network bool success = socket->send( //Sirikata::MemoryReference(&(data[0]), data.size()), Sirikata::MemoryReference(data), Sirikata::Network::ReliableOrdered ); if (success) { TIMESTAMP_END(tstamp, Trace::OH_HIT_NETWORK); } else { TIMESTAMP_END(tstamp, Trace::OH_DROPPED_AT_SEND); TRACE_DROP(OH_DROPPED_AT_SEND); } return success; }