SOME/IP开源库Vsomeip分析3-hello_world_client分析

前言

前一章我们主要分析了hello_world_service的运行过程进行了简单的分析,这一章我们会对client进行更深层次的分析。

init

这里初始化其实和之前service端类似,也是注册了几个回调函数,其中比service端多注册了一个回调函数就是on_availability_cbk这个函数,这个函数在上一章也提到了,service端在offer server操作成功后,会通知client端,最终就调用到了这个函数。

    // Get the vSomeIP runtime and
    // create a application via the runtime, we could pass the application name
    // here otherwise the name supplied via the VSOMEIP_APPLICATION_NAME
    // environment variable is used
    hello_world_client() :
                    rtm_(vsomeip::runtime::get()),
                    app_(rtm_->create_application())
    {
    }

    bool init(){
        // init the application
        if (!app_->init()) {
            LOG_ERR ("Couldn't initialize application");
            return false;
        }

        // register a state handler to get called back after registration at the
        // runtime was successful
        app_->register_state_handler(
                std::bind(&hello_world_client::on_state_cbk, this,
                        std::placeholders::_1));

        // register a callback for responses from the service
        app_->register_message_handler(vsomeip::ANY_SERVICE,
                service_instance_id, vsomeip::ANY_METHOD,
                std::bind(&hello_world_client::on_message_cbk, this,
                        std::placeholders::_1));

        // register a callback which is called as soon as the service is available
        app_->register_availability_handler(service_id, service_instance_id,
                std::bind(&hello_world_client::on_availability_cbk, this,
                        std::placeholders::_1, std::placeholders::_2,
                        std::placeholders::_3));
        return true;
    }

on_avaliability_cbk

当服务连接成功后调用。这个函数中主要先判断了当前连接的是否时helloworld服务,然后创建对应的request message,发送对应的请求。

//当服务连接成功时,调用该回调函数
 void on_availability_cbk(vsomeip::service_t _service,
            vsomeip::instance_t _instance, bool _is_available)
    {
        //检查当前连接的服务是否时helloworld服务
        // Check if the available service is the the hello world service
        if(service_id == _service && service_instance_id == _instance
                && _is_available)
        {
            // The service is available then we send the request
            // Create a new request
            //创建一个request的message,默认的requst message还需要自己设置对应的service信息
            std::shared_ptr rq = rtm_->create_request();
            // Set the hello world service as target of the request
            //设置request中的相关参数,someip包头的部分
            rq->set_service(service_id);
            rq->set_instance(service_instance_id);
            rq->set_method(service_method_id);

            // Create a payload which will be sent to the service
            //创建对应的payload
            std::shared_ptr pl = rtm_->create_payload();
            std::string str("World");
            std::vector pl_data(std::begin(str), std::end(str));

            pl->set_data(pl_data);
            rq->set_payload(pl);
            // Send the request to the service. Response will be delivered to the
            // registered message handler
            LOG_INF("Sending: %s", str.c_str());
            //发送request
            app_->send(rq);
        }
    }

rtm_->create_request

runtime层默认处理了request message中需要的一些信息。

std::shared_ptr runtime_impl::create_request(bool _reliable) const {
    std::shared_ptr its_request =
            std::make_shared();
    its_request->set_protocol_version(VSOMEIP_PROTOCOL_VERSION);
    its_request->set_message_type(message_type_e::MT_REQUEST);
    its_request->set_return_code(return_code_e::E_OK);
    its_request->set_reliable(_reliable);
    its_request->set_interface_version(DEFAULT_MAJOR);
    return (its_request);
}

app_->send

void application_impl::send(std::shared_ptr _message) {
 bool is_request = utility::is_request(_message);

    //如果logging功能开启了,这里先记录client的行为
    if (client_side_logging_
        && (client_side_logging_filter_.empty()
            || (1 == client_side_logging_filter_.count(std::make_tuple(_message->get_service(), ANY_INSTANCE)))
            || (1 == client_side_logging_filter_.count(std::make_tuple(_message->get_service(), _message->get_instance()))))) {
        ...
    }
 
    //如果routing存在,请求routing
    if (routing_) {
        // in case of requests set the request-id (client-id|session-id)
        if (is_request) {
            //如果时request message,在message里面设置对应的client和session信息
            _message->set_client(client_);
            _message->set_session(get_session());
        }
        // Always increment the session-id
        //发送给routing proxy
        (void)routing_->send(client_, _message);
    }
}

routing_->send

由于helloworld client没有注册对应的routing,因此这里去调用routing proxy处理

//序列化相关消息,然后交给其他函数继续发送
bool routing_manager_base::send(client_t _client,
        std::shared_ptr _message) {
 bool is_sent(false);
    if (utility::is_request(_message->get_message_type())) {
        _message->set_client(_client);
    }

    std::shared_ptr its_serializer(get_serializer());
    if (its_serializer->serialize(_message.get())) {
        is_sent = send(_client, its_serializer->get_data(),
                its_serializer->get_size(), _message->get_instance(),
                _message->is_reliable(), get_client(), std::make_pair(ANY_UID, ANY_GID), 0, false);
        its_serializer->reset();
        put_serializer(its_serializer);
    } else {
        VSOMEIP_ERROR << "Failed to serialize message. Check message size!";
    }
    return (is_sent);
}

然后调用proxy的send函数

bool routing_manager_proxy::send(client_t _client, const byte_t *_data,
        length_t _size, instance_t _instance,
 bool _reliable,
        client_t _bound_client,
        credentials_t _credentials,
 uint8_t _status_check,
 bool _sent_from_remote) {
    ...
    //如果当前状态不是registered,那么直接返回false
    {
        std::lock_guard its_lock(state_mutex_);
        if (state_ != inner_state_type_e::ST_REGISTERED) {
            return false;
        }
    }
    //打开了logging功能的话,记录相关信息
    if (client_side_logging_) {
        if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
            service_t its_service = VSOMEIP_BYTES_TO_WORD(
                    _data[VSOMEIP_SERVICE_POS_MIN],
                    _data[VSOMEIP_SERVICE_POS_MAX]);
            if (client_side_logging_filter_.empty()
                || (1 == client_side_logging_filter_.count(std::make_tuple(its_service, ANY_INSTANCE)))
                || (1 == client_side_logging_filter_.count(std::make_tuple(its_service, _instance)))) {
                method_t its_method = VSOMEIP_BYTES_TO_WORD(
                        _data[VSOMEIP_METHOD_POS_MIN],
                        _data[VSOMEIP_METHOD_POS_MAX]);
                session_t its_session = VSOMEIP_BYTES_TO_WORD(
                        _data[VSOMEIP_SESSION_POS_MIN],
                        _data[VSOMEIP_SESSION_POS_MAX]);
                client_t its_client = VSOMEIP_BYTES_TO_WORD(
                        _data[VSOMEIP_CLIENT_POS_MIN],
                        _data[VSOMEIP_CLIENT_POS_MAX]);
               ...
            }
        } else {
            ...
        }
    }
    //检查message 长度是否合法
    if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
        std::shared_ptr its_target;
        if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
            // Request
            //从message中读取service id信息
            service_t its_service = VSOMEIP_BYTES_TO_WORD(
                    _data[VSOMEIP_SERVICE_POS_MIN],
                    _data[VSOMEIP_SERVICE_POS_MAX]);
            //查找本地缓存中是否存在对应的service信息
            client_t its_client = find_local_client(its_service, _instance);
            //这里如果已经查到,那么直接用已有的ep连接
            if (its_client != VSOMEIP_ROUTING_CLIENT) {
                if (is_client_known(its_client)) {
                    its_target = ep_mgr_->find_or_create_local(its_client);
                }
            }
        } else if (!utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
            ...
        } else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) &&
                _client == VSOMEIP_ROUTING_CLIENT) {
            ...
        } else if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]) &&
                _client != VSOMEIP_ROUTING_CLIENT) {
            // notify_one
            its_target = ep_mgr_->find_local(_client);
            if (its_target) {
                ...
                return send_local(its_target, get_client(), _data, _size,
                        _instance, _reliable, VSOMEIP_SEND, _status_check);
            }
        }
        // If no direct endpoint could be found
        // or for notifications ~> route to routing_manager_stub
        //如果找不到endpoint或通知-> 那么直接路由到routing_manager_stub
#ifdef USE_DLT
 bool message_to_stub(false);
#endif
        if (!its_target) {
            std::lock_guard its_lock(sender_mutex_);
            //如果之前没有连接过,这里路由到routing_manager_stub。
            if (sender_) {
                its_target = sender_;
#ifdef USE_DLT
                message_to_stub = true;
#endif
            } else {
                return false;
            }
        }

 bool send(true);
 uint8_t command = VSOMEIP_SEND;

        if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
            if (_client != VSOMEIP_ROUTING_CLIENT) {
                command = VSOMEIP_NOTIFY_ONE;
            } else {
                command = VSOMEIP_NOTIFY;
                // Do we need to deliver a notification to the routing manager?
                // Only for services which already have remote clients subscribed to
                send = has_remote_subscribers;
            }
        }
        ...
        if (send) {
            //发送消息给对应的routing_stub
            is_sent = send_local(its_target,
                    (command == VSOMEIP_NOTIFY_ONE ? _client : get_client()),
                    _data, _size, _instance, _reliable, command, _status_check);
        }
    }
    return (is_sent);
}

紧接着,设置本地socket通信的相关header,然后转发消息给stub

bool routing_manager_base::send_local(
        std::shared_ptr& _target, client_t _client,
 const byte_t *_data, uint32_t _size, instance_t _instance,
 bool _reliable, uint8_t _command, uint8_t _status_check) const {
 const std::size_t its_complete_size = VSOMEIP_SEND_COMMAND_SIZE
            - VSOMEIP_COMMAND_HEADER_SIZE + _size;
 const client_t sender = get_client();

    //设置本地socket通信的相关header信息
    std::vector its_command_header(VSOMEIP_SEND_COMMAND_SIZE);
    its_command_header[VSOMEIP_COMMAND_TYPE_POS] = _command;
    std::memcpy(&its_command_header[VSOMEIP_COMMAND_CLIENT_POS],
            &sender, sizeof(client_t));
    std::memcpy(&its_command_header[VSOMEIP_COMMAND_SIZE_POS_MIN],
            &its_complete_size, sizeof(_size));
    std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
            &_instance, sizeof(instance_t));
    std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
            &_reliable, sizeof(bool));
    std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
            &_status_check, sizeof(uint8_t));
    // Add target client, only relevant for selective notifications
    std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN],
            &_client, sizeof(client_t));

    return _target->send(its_command_header, _data, _size);
}

routing_manager_stub::on_message

这里主要做了如下的几件事,解析对应的command获取service信息,然后对client进行安全检查

 case VSOMEIP_SEND: {
                if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
                    VSOMEIP_WARNING << "Received a SEND command with too small size ~> skip!";
                    break;
                }
                //获取payload信息
                its_data = &_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS];
                its_service = VSOMEIP_BYTES_TO_WORD(
                                its_data[VSOMEIP_SERVICE_POS_MIN],
                                its_data[VSOMEIP_SERVICE_POS_MAX]);
                its_client_from_header = VSOMEIP_BYTES_TO_WORD(
                        its_data[VSOMEIP_CLIENT_POS_MIN],
                        its_data[VSOMEIP_CLIENT_POS_MAX]);
                its_method = VSOMEIP_BYTES_TO_WORD(
                        its_data[VSOMEIP_METHOD_POS_MIN],
                        its_data[VSOMEIP_METHOD_POS_MAX]);
                std::memcpy(&its_instance, &_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
                            sizeof(its_instance));
                std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
                            sizeof(its_reliable));
                std::memcpy(&its_check_status, &_data[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
                            sizeof(its_check_status));

                // Allow response messages from local proxies as answer to remote requests
                // but check requests sent by local proxies to remote against policy.
                //允许来自本地代理的响应消息作为对远程请求的应答,但根据策略检查本地代理发送到远程的请求。
                //这里如果时response可以正常回复,但是如果时request,那么就要检查策略
                if (utility::is_request(its_data[VSOMEIP_MESSAGE_TYPE_POS])) {
                    if (!security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
                            its_client_from_header, its_service, its_instance, its_method)) {
                        ...
                        return;
                    }
                }
                // reduce by size of instance, flush, reliable, client and is_valid_crc flag
 const std::uint32_t its_message_size = its_size -
                        (VSOMEIP_SEND_COMMAND_SIZE - VSOMEIP_COMMAND_HEADER_SIZE);
                if (its_message_size !=
                        VSOMEIP_BYTES_TO_LONG(_data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN],
                                              _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 1],
                                              _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 2],
                                              _data[VSOMEIP_SEND_COMMAND_PAYLOAD_POS + VSOMEIP_LENGTH_POS_MIN + 3])
                        + VSOMEIP_SOMEIP_HEADER_SIZE) {
                    ...                    
break;
                }
                host_->on_message(its_service, its_instance, its_data, its_message_size,
                        its_reliable, _bound_client, _credentials, its_check_status, false);
                break;
            }

对相关client发来的消息进行检查后,会吧对应的消息转发给routing_manager_impl做进一步处理

routing_manager_impl::on_message

这里首先去获取routing进程中存储的service的信息,相关的service可能存在2种情况、

  1. 需要接收消息的service就是routing进程本身,这时候会去调用deliver_message函数
  2. 需要接收消息的service不是routing进程,这个时候会去继续转发相关的消息。
bool routing_manager_impl::on_message(
        service_t _service, instance_t _instance,
 const byte_t *_data, length_t _size,
 bool _reliable, client_t _bound_client,
        credentials_t _credentials,
 uint8_t _check_status,
 bool _is_from_remote) {
...
    client_t its_client;
 bool is_forwarded(true);

    if (utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
        its_client = find_local_client(_service, _instance);
    } else {
        its_client = VSOMEIP_BYTES_TO_WORD(
                _data[VSOMEIP_CLIENT_POS_MIN],
                _data[VSOMEIP_CLIENT_POS_MAX]);
    }

    if (utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS])) {
        is_forwarded = deliver_notification(_service, _instance, _data, _size,
                _reliable, _bound_client, _credentials, _check_status, _is_from_remote);
    } else if (its_client == host_->get_client()) {
        //如果需要发送的client就是host自己的话,直接转发给自己
        deliver_message(_data, _size, _instance,
                _reliable, _bound_client, _credentials, _check_status, _is_from_remote);
    } else {
        //这里说明是远程的连接,继续send消息
        send(its_client, _data, _size, _instance, _reliable,
                _bound_client, _credentials, _check_status, _is_from_remote); //send to proxy
    }
    return is_forwarded;
}

routing_manager_impl::deliver_message

由于我们的hellowrld service自己本身就是routing进程,因此这里直接转发给自己去处理消息。

这里主要是解析了对应的ipc消息,然后重新组织成someip的message供上层使用。

其次在此基础上做了相关的安全检查,检查client是否可以去send操作。

bool routing_manager_impl::deliver_message(const byte_t *_data, length_t _size,
        instance_t _instance, bool _reliable, client_t _bound_client, credentials_t _credentials,
 uint8_t _status_check, bool _is_from_remote) {
 bool is_delivered(false);
    std::uint32_t its_sender_uid = std::get<0>(_credentials);
    std::uint32_t its_sender_gid = std::get<1>(_credentials);

 auto its_deserializer = get_deserializer();
    its_deserializer->set_data(_data, _size);
    std::shared_ptr its_message(its_deserializer->deserialize_message());
    its_deserializer->reset();
    put_deserializer(its_deserializer);

    if (its_message) {
        //重新设置message的信息
        its_message->set_instance(_instance);
        its_message->set_reliable(_reliable);
        its_message->set_check_result(_status_check);
        its_message->set_uid(std::get<0>(_credentials));
        its_message->set_gid(std::get<1>(_credentials));

        //本地检查对应的uid,gid信息,但是远程,只去检查is_remote_client_allowed
        //检查需要转发的消息是来自本地还是远程的
        if (!_is_from_remote) {
...

            //如果该消息是一个request消息
            } else if (utility::is_request(its_message->get_message_type())) {
                if (security::get()->is_enabled()
                        && its_message->get_client() != _bound_client) {
                    ...
                    return false;
                }
                //检查策略,当前的uid是否可以request对应的服务
                if (!security::get()->is_client_allowed(its_sender_uid, its_sender_gid,
                        its_message->get_client(), its_message->get_service(),
                        its_message->get_instance(), its_message->get_method())) {
                    ...
                    return false;
                }

...

        host_->on_message(std::move(its_message));
        is_delivered = true;
    } else {
        VSOMEIP_ERROR << "Routing manager: deliver_message: "
                      << "SomeIP-Header deserialization failed!";
    }
    return is_delivered;
}

application_impl::on_message

对应的routing_impl会调回到自身进程的application_impl函数。

service进程在注册对应on_message回调函数的时候,会将对应的信息存储在members中,这里主要做的事情就是查找members存储的回调函数。

然后调用对应的回调函数

//消息过来时,遍历对应的回调函数,然后根据serviceid,instanceid,methodid查找对应的回调函数
void application_impl::on_message(std::shared_ptr &&_message) {
 const service_t its_service = _message->get_service();
 const instance_t its_instance = _message->get_instance();
 const method_t its_method = _message->get_method();

    if (_message->get_message_type() == message_type_e::MT_NOTIFICATION) {
        if (!check_for_active_subscription(its_service, its_instance,
                static_cast(its_method))) {
            ...
            return;
        }
    }

    {
        std::lock_guard its_lock(members_mutex_);
        std::set its_handlers;
 auto found_service = members_.find(its_service);
        if (found_service != members_.end()) {
 auto found_instance = found_service->second.find(its_instance);
            if (found_instance != found_service->second.end()) {
 auto found_method = found_instance->second.find(its_method);
                if (found_method != found_instance->second.end()) {
                    its_handlers.insert(found_method->second);
                }
 auto found_any_method = found_instance->second.find(ANY_METHOD);
                if (found_any_method != found_instance->second.end()) {
                    its_handlers.insert(found_any_method->second);
                }
            }
 auto found_any_instance = found_service->second.find(ANY_INSTANCE);
            if (found_any_instance != found_service->second.end()) {
 auto found_method = found_any_instance->second.find(its_method);
                if (found_method != found_any_instance->second.end()) {
                    its_handlers.insert(found_method->second);
                }
 auto found_any_method = found_any_instance->second.find(ANY_METHOD);
                if (found_any_method != found_any_instance->second.end()) {
                    its_handlers.insert(found_any_method->second);
                }
            }
        }
 auto found_any_service = members_.find(ANY_SERVICE);
        if (found_any_service != members_.end()) {
 auto found_instance = found_any_service->second.find(its_instance);
            if (found_instance != found_any_service->second.end()) {
 auto found_method = found_instance->second.find(its_method);
                if (found_method != found_instance->second.end()) {
                    its_handlers.insert(found_method->second);
                }
 auto found_any_method = found_instance->second.find(ANY_METHOD);
                if (found_any_method != found_instance->second.end()) {
                    its_handlers.insert(found_any_method->second);
                }
            }
 auto found_any_instance = found_any_service->second.find(ANY_INSTANCE);
            if (found_any_instance != found_any_service->second.end()) {
 auto found_method = found_any_instance->second.find(its_method);
                if (found_method != found_any_instance->second.end()) {
                    its_handlers.insert(found_method->second);
                }
 auto found_any_method = found_any_instance->second.find(ANY_METHOD);
                if (found_any_method != found_any_instance->second.end()) {
                    its_handlers.insert(found_any_method->second);
                }
            }
        }

        if (its_handlers.size()) {
            std::lock_guard its_lock(handlers_mutex_);
            for (const auto &its_handler : its_handlers) {
 auto handler = its_handler.handler_;
                std::shared_ptr its_sync_handler =
                        std::make_shared([handler, _message]() {
                            handler(_message);
                        });
                its_sync_handler->handler_type_ = handler_type_e::MESSAGE;
                its_sync_handler->service_id_ = _message->get_service();
                its_sync_handler->instance_id_ = _message->get_instance();
                its_sync_handler->method_id_ = _message->get_method();
                its_sync_handler->session_id_ = _message->get_session();
                handlers_.push_back(its_sync_handler);
            }
            dispatcher_condition_.notify_one();
        }
    }
}

这里在注册回调函数的时候,对应的服务的on_message回调函数会存储在members_里面。因此这里可以找到对应的members里的回调函数,调用hellworld的on_message函数

routing_manager_impl::send

如果需要请求的服务不是routing进程本身,routing继续发送对应的消息给真正的service

//routing代理发给_client对应的服务,send的客户端的id是_bound_client
bool routing_manager_impl::send(client_t _client, const byte_t *_data,
        length_t _size, instance_t _instance, bool _reliable,
        client_t _bound_client,
        credentials_t _credentials,
 uint8_t _status_check, bool _sent_from_remote) {
 bool is_sent(false);
    if (_size > VSOMEIP_MESSAGE_TYPE_POS) {
        std::shared_ptr its_target;
 bool is_request = utility::is_request(_data[VSOMEIP_MESSAGE_TYPE_POS]);
 bool is_notification = utility::is_notification(_data[VSOMEIP_MESSAGE_TYPE_POS]);
 bool is_response = utility::is_response(_data[VSOMEIP_MESSAGE_TYPE_POS]);

        client_t its_client = VSOMEIP_BYTES_TO_WORD(_data[VSOMEIP_CLIENT_POS_MIN],
                _data[VSOMEIP_CLIENT_POS_MAX]);
        service_t its_service = VSOMEIP_BYTES_TO_WORD(
                _data[VSOMEIP_SERVICE_POS_MIN], _data[VSOMEIP_SERVICE_POS_MAX]);
        method_t its_method = VSOMEIP_BYTES_TO_WORD(
                _data[VSOMEIP_METHOD_POS_MIN], _data[VSOMEIP_METHOD_POS_MAX]);

 bool is_service_discovery
            = (its_service == sd::service && its_method == sd::method);

        if (is_request) {
            its_target = ep_mgr_->find_local(its_service, _instance);
        } else if (!is_notification) {
            its_target = find_local(its_client);
        } else if (is_notification && _client && !is_service_discovery) { // Selective notifications!
            if (_client == get_client()) {
...
}


        if (its_target) {
#ifdef USE_DLT
            if ((is_request && its_client == get_client()) ||
                    (is_response && find_local_client(its_service, _instance) == get_client())) {
 const uint16_t its_data_size
                    = uint16_t(_size > USHRT_MAX ? USHRT_MAX : _size);

                trace::header its_header;
                if (its_header.prepare(its_target, true, _instance))
                    tc_->trace(its_header.data_, VSOMEIP_TRACE_HEADER_SIZE,
                            _data, its_data_size);
            }
#endif
            //通过本地socket发送消息给对应的服务端
            is_sent = send_local(its_target, get_client(), _data, _size, _instance, _reliable, VSOMEIP_SEND, _status_check);


routing_manager_base::send_local

重新序列化ipc的消息,发送对应的消息给proxy

bool routing_manager_base::send_local(
        std::shared_ptr& _target, client_t _client,
 const byte_t *_data, uint32_t _size, instance_t _instance,
 bool _reliable, uint8_t _command, uint8_t _status_check) const {
 const std::size_t its_complete_size = VSOMEIP_SEND_COMMAND_SIZE
            - VSOMEIP_COMMAND_HEADER_SIZE + _size;
 const client_t sender = get_client();

    //设置本地socket通信的相关header信息
    std::vector its_command_header(VSOMEIP_SEND_COMMAND_SIZE);
    its_command_header[VSOMEIP_COMMAND_TYPE_POS] = _command;
    std::memcpy(&its_command_header[VSOMEIP_COMMAND_CLIENT_POS],
            &sender, sizeof(client_t));
    std::memcpy(&its_command_header[VSOMEIP_COMMAND_SIZE_POS_MIN],
            &its_complete_size, sizeof(_size));
    std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
            &_instance, sizeof(instance_t));
    std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
            &_reliable, sizeof(bool));
    std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
            &_status_check, sizeof(uint8_t));
    // Add target client, only relevant for selective notifications
    std::memcpy(&its_command_header[VSOMEIP_SEND_COMMAND_DST_CLIENT_POS_MIN],
            &_client, sizeof(client_t));

    return _target->send(its_command_header, _data, _size);
}

routing_manager_proxy::on_message

这里的proxy应该是server端的proxy,首先解析相关的命令,然后做了一些安全检查,最后调用host_->on_message

void routing_manager_proxy::on_message(const byte_t *_data, length_t _size,
        endpoint *_receiver, const boost::asio::ip::address &_destination,
        client_t _bound_client,
        credentials_t _credentials,
 const boost::asio::ip::address &_remote_address,
        std::uint16_t _remote_port) {
    (void)_receiver;
    (void)_destination;
    (void)_remote_address;
(void)_remote_port;
...
 bool message_from_routing(false);
        if (its_security->is_enabled()) {
            // if security is enabled, client ID of routing must be configured
            // and credential passing is active. Otherwise bound client is zero by default
            message_from_routing = (_bound_client == routing_host_id);
        } else {
            message_from_routing = (its_client == routing_host_id);
        }

        //如果这里安全功能打开了,那么这里proxy收到的消息必须是routing的,或者是他自己
        if (its_security->is_enabled() && !message_from_routing &&
                _bound_client != its_client) {
            VSOMEIP_WARNING << std::hex << "Client " << std::setw(4) << std::setfill('0') << get_client()
                    << " received a message with command " << (uint32_t)its_command
                    << " from " << std::setw(4) << std::setfill('0')
                    << its_client << " which doesn't match the bound client "
                    << std::setw(4) << std::setfill('0') << _bound_client
                    << " ~> skip message!";
            return;
        }
...
case VSOMEIP_SEND: {
            if (_size < VSOMEIP_SEND_COMMAND_SIZE + VSOMEIP_FULL_HEADER_SIZE) {
                VSOMEIP_WARNING << "Received a SEND command with too small size -> skip!";
                break;
            }
            instance_t its_instance;
 bool its_reliable;
 uint8_t its_check_status;
            std::memcpy(&its_instance,&_data[VSOMEIP_SEND_COMMAND_INSTANCE_POS_MIN],
                        sizeof(instance_t));
            std::memcpy(&its_reliable, &_data[VSOMEIP_SEND_COMMAND_RELIABLE_POS],
                        sizeof(its_reliable));

            std::memcpy(&its_check_status, &_data[VSOMEIP_SEND_COMMAND_CHECK_STATUS_POS],
                        sizeof(its_check_status));
...
if (its_message) {
                //重组对应的someip的message
                its_message->set_instance(its_instance);
                its_message->set_reliable(its_reliable);
                its_message->set_check_result(its_check_status);
                its_message->set_uid(std::get<0>(_credentials));
                its_message->set_gid(std::get<1>(_credentials));
                if (!message_from_routing) {
                    //做对应的安全检查
...
}

                host_->on_message(std::move(its_message));

总结

这里整个发消息的过程实际上

SOME/IP开源库Vsomeip分析3-hello_world_client分析_第1张图片

由于helloworld的测试程序都是在本地运行的,因此整个过程实际上是不涉及远程的网络通信的,都是本地的ipc通信。但是其实整个过程中,由于routing的存在,someip本身的消息实际上是被转了好几道手。

首先,在client进程到routing进程这段,会先把原本的someip message转换成本地ipc的message,其次,在routing进程转发service的过程中,由于也是ipc通信,因此也是使用的本地ipc的message格式。最终,到达service端,会将对应的message还原成someip的message。

你可能感兴趣的:(vsomeip,汽车,分布式,网络协议,物联网,系统安全)