Руслан Урядинский / libuavcan

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers uc_service_client.cpp Source File

uc_service_client.cpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #include <uavcan/node/service_client.hpp>
00006 
00007 namespace uavcan
00008 {
00009 /*
00010  * ServiceClientBase::CallState
00011  */
00012 void ServiceClientBase::CallState::handleDeadline(MonotonicTime)
00013 {
00014     UAVCAN_TRACE("ServiceClient::CallState", "Timeout from nid=%d, tid=%d, dtname=%s",
00015                  int(id_.server_node_id.get()), int(id_.transfer_id.get()),
00016                  (owner_.data_type_descriptor_ == UAVCAN_NULLPTR) ? "???" : owner_.data_type_descriptor_->getFullName());
00017     /*
00018      * What we're doing here is relaying execution from this call stack to a different one.
00019      * We need it because call registry cannot release memory from this callback, because this will destroy the
00020      * object method of which we're executing now.
00021      */
00022     UAVCAN_ASSERT(timed_out_ == false);
00023     timed_out_ = true;
00024     owner_.generateDeadlineImmediately();
00025     UAVCAN_TRACE("ServiceClient::CallState", "Relaying execution to the owner's handler via timer callback");
00026 }
00027 
00028 /*
00029  * ServiceClientBase
00030  */
00031 int ServiceClientBase::prepareToCall(INode& node,
00032                                      const char* dtname,
00033                                      NodeID server_node_id,
00034                                      ServiceCallID& out_call_id)
00035 {
00036     /*
00037      * Making sure we're not going to get transport error because of invalid input data
00038      */
00039     if (!server_node_id.isUnicast() || (server_node_id == node.getNodeID()))
00040     {
00041         UAVCAN_TRACE("ServiceClient", "Invalid Server Node ID");
00042         return -ErrInvalidParam;
00043     }
00044     out_call_id.server_node_id = server_node_id;
00045 
00046     /*
00047      * Determining the Data Type ID
00048      */
00049     if (data_type_descriptor_ == UAVCAN_NULLPTR)
00050     {
00051         GlobalDataTypeRegistry::instance().freeze();
00052         data_type_descriptor_ = GlobalDataTypeRegistry::instance().find(DataTypeKindService, dtname);
00053         if (data_type_descriptor_ == UAVCAN_NULLPTR)
00054         {
00055             UAVCAN_TRACE("ServiceClient", "Type [%s] is not registered", dtname);
00056             return -ErrUnknownDataType;
00057         }
00058         UAVCAN_TRACE("ServiceClient", "Data type descriptor inited: %s", data_type_descriptor_->toString().c_str());
00059     }
00060     UAVCAN_ASSERT(data_type_descriptor_ != UAVCAN_NULLPTR);
00061 
00062     /*
00063      * Determining the Transfer ID
00064      */
00065     const OutgoingTransferRegistryKey otr_key(data_type_descriptor_->getID(),
00066                                               TransferTypeServiceRequest, server_node_id);
00067     const MonotonicTime otr_deadline = node.getMonotonicTime() + TransferSender::getDefaultMaxTransferInterval();
00068     TransferID* const otr_tid =
00069         node.getDispatcher().getOutgoingTransferRegistry().accessOrCreate(otr_key, otr_deadline);
00070     if (!otr_tid)
00071     {
00072         UAVCAN_TRACE("ServiceClient", "OTR access failure, dtd=%s", data_type_descriptor_->toString().c_str());
00073         return -ErrMemory;
00074     }
00075     out_call_id.transfer_id = *otr_tid;
00076     otr_tid->increment();
00077 
00078     return 0;
00079 }
00080 
00081 }