1. search_pkg_server为测试服务器代码,先将search_pkg_server文件夹拷贝到base/update/updateservice下

  2. 修改base/update/updateservice下的bundle.json文件。在bundle.json文件的sub_component中添加:

"build": {
    "sub_component": [
+       "//base/update/updateservice/search_pkg_server:SearchPkgServer",
        "//base/update/updateservice/frameworks/js/napi/client:update",

  1. 编译服务器二进制文件。

执行编译命令:./build.sh --product-name rk3568 --build-target=SearchPkgServer --ccache后,会生成SearchPkgServer二进制文件,可在out/rk3568/updater/update_service/下找到该文件。

  1. 执行命令行:

openssl req -newKey rsa:2048 -nodes -keyout serverKey.pem -x509 -days 365 -out serverCert.cer -subj "/C=CN/ST=GD/L=GZ/O=abc/OU=defg/CN=hijk/emailAddress=test.com"

会生成serverCert.cer和serverKey.pem两个文件。

  1. 将SearchPkgServer,serverCert.cer和serverKey.pem三个文件放到同一个文件夹下(例如文件夹命名为testServer),将testServer推到开发板的data目录下,进入该目录,增加SearchPkgServer可执行权限(chmod +x SearchPkgServer),然后执行./SearchPkgServer即可启动服务器。

  2. 启动测试前需要确认如下处理:

    6.1 ota升级会毕竟系统版本号,例如当前系统版本为OpenHarmony 3.2.8.3,那么在制作升级包时VERSION.mbn文件中需要加上该版本号。

    6.2 制作好升级包后,将包信息填入服务器代码search_pkg_server.cpp的回复信息respondContent中:

    size字段为包大小;

    verifyInfo字段为升级包的sha256字符串,linux下通过命令:"sha256sum 文件"可获取,windows下通过命令:"certutil -hashfile 文件 sha256"可获取;

    versionName为用于客户判断升级包中是否有该版本号,有该版本号才能升级成功,在制作升级包时的VERSION.mbn中配置;

    versionCode为客户端用于比较的产品版本号;

    url为升级包下载地址;

        6.3 配置tomcat下载服务器,将升级包放到下载服务器上,在url字段中配置下载地址,确认开发板是否可访问下载服务器。

        6.4 客户端升级版本号需要修改该配置文件:

        startup/init/services/etc/param/ohos.para

        属性:const.product.software.version=OpenHarmony 3.2.8.3 //用于设置中的系统版本号显示

        hw_sc.build.os.version=2.2.0 //用于升级时的系统版本号比较,服务器配置的versionCode版本号需要大于本地版本号才 会判定有新的升级包。

  1. OTA测试服务器代码:

         ​​7.1 代码目录结构:

         

        7.2 search_pkg_server.h头文件:

#ifndef SEARCH_PKG_SERVER_H
#define SEARCH_PKG_SERVER_H

#include <unistd.h>
#include "singleton.h"

#include <arpa/inet.h>
#include <limits.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>

#include "openssl/err.h"
#include "openssl/ssl.h"

namespace OHOS {
namespace UpdateEngine {
constexpr const char *SERVER_PEM = "./serverKey.pem";
constexpr const char *SERVER_CER = "./serverCert.cer";
constexpr const int32_t DEFAULT_SLEEP = 1000;
constexpr const unsigned short DEFAULT_PORT = 5022;
constexpr const unsigned short DEFAULT_TTL = 60;

struct S_NetEnv {
    int32_t socketId;
    SSL_CTX *sslctx;
};

struct S_NetParam {
    unsigned short port;
    unsigned short ttl;
    std::string respondContent;
    uint32_t contentLen;
    uint32_t maxConn;
};

class SearchPkgServer : public DelayedSingleton<SearchPkgServer> {
    DECLARE_DELAYED_SINGLETON(SearchPkgServer);
public:
    int32_t Init();
    int32_t Open();
    int32_t MainLoop();
    int32_t Close();

private:
    S_NetEnv S_NetEnv_;
    S_NetParam S_NetParam_;
};

#define SERVER_PRINT(fmt, ...) printf("[SearchPkgServer][%s:%d] " fmt "\n", __func__, __LINE__, ##__VA_ARGS__)
#define SERVER_CHECK(cond, log, ...)\
    if (!(cond)) {\
        SERVER_PRINT(log);\
        __VA_ARGS__;\
        return -1;\
    }
}   //namespace UpdateEngine
}   //namespace OHOS
#endif

        7.3 search_pkg_server.cpp文件:

#include "search_pkg_server.h"

namespace OHOS {
namespace UpdateEngine {
SearchPkgServer::SearchPkgServer() {}

SearchPkgServer::~SearchPkgServer() {}

int32_t SearchPkgServer::Init()
{
    S_NetParam_.port = DEFAULT_PORT;
    S_NetParam_.ttl = DEFAULT_TTL;
    S_NetParam_.respondContent = "{"
        "\"searchStatus\": 0,"
        "\"errMsg\": \"success\","
        "\"checkResults\": [{"
            "\"versionName\": \"OpenHarmony 3.2.8.4\","
            "\"versionCode\": \"2.2.1\","
            "\"verifyInfo\": \"**************************************\","         //升级包的sha256字符串
            "\"size\": \"123456789\","           //包字节数
            "\"packageType\": 1,"
            "\"url\": "
            "\"http://ip:port/download/updater.zip\","      //使用自己下载服务器的ip地址和端口
            "\"descriptPackageId\": \"Searver_testonly-descriptPackageId\""
        "}],"
        "\"descriptInfo\": [{"
            "\"descriptionType\": 0,"
            "\"content\": \"This package is dispatched, which should be used for test situation only. \""
        "}],"
    "}";
    S_NetParam_.contentLen = strlen(S_NetParam_.respondContent.c_str());
    S_NetEnv_.socketId = -1;
    S_NetEnv_.sslctx = NULL;
    return 0;
}

int32_t SearchPkgServer::Open()
{
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    S_NetEnv_.sslctx = SSL_CTX_new(SSLv23_server_method());
    SERVER_CHECK(S_NetEnv_.sslctx != NULL, "Error: Create sslctx failed.", Close());

    int32_t rv = SSL_CTX_use_certificate_file(S_NetEnv_.sslctx, realpath(SERVER_CER, NULL), SSL_FILETYPE_PEM);
    SERVER_CHECK(rv == 1, "Error: SSL use cert file failed.", Close());

    int32_t rv = SSL_CTX_use_PrivateKey_file(S_NetEnv_.sslctx, realpath(SERVER_PEM, NULL), SSL_FILETYPE_PEM);
    SERVER_CHECK(rv == 1, "Error: SSL use pem file failed.", Close());

    int32_t rv = SSL_CTX_check_private_key(S_NetEnv_.sslctx);
    SERVER_CHECK(rv == 1, "Error: SSL check pem failed.", Close());

    S_NetEnv_.socketId = socket(PF_INET, SOCK_STREAM, 0);
    SERVER_CHECK(S_NetEnv_.socketId >= 0, "Error: create socket failed.", Close());

    int32_t opt = 1;
    setsockopt(S_NetEnv_.socketId, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    setsockopt(S_NetEnv_.socketId, SOL_SOCKET, SOCK_NONBLOCK, &opt, sizeof(opt));

    struct sockaddr_in serverAddr = {0};
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = htons(INADDR_ANY);
    serverAddr.sin_port = htons(S_NetParam_.port);
    int32_t ret = bind(S_NetEnv_.socketId, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
    SERVER_CHECK(ret >= 0, "Error: bind socket failed.", Close());

    ret = listen(S_NetEnv_.socketId, 32);
    SERVER_CHECK(ret >= 0, "Error: listen failed.", Close());

    return 0;
}

int32_t SearchPkgServer::MainLoop()
{
    struct sockaddr_in clientAddr = {0};
    socklen_t length = sizeof(clientAddr);

    int32_t clientSocketId = accept(S_NetEnv_.socketId, (struct sockaddr*)&clientAddr, &length);
    if(clientSocketId < 0) {
        if(errno != EAGAIN && errno != EWOULDBLOCK) {
            SERVER_PRINT("Error: Accept client conncetion failed. ret = %d", errno);
            return -1;
        } else {
            return 0;
        }
    }

    SERVER_PRINT("Info: Accept One Serach pkg request. IP is %s, port is %d", inet_ntoa(clientAddr.sin_addr),
        ntohs(clientAddr.sin_port));
    SSL *ssl = SSL_new(S_NetEnv_.sslctx);
    if(ssl == NULL) {
        SERVER_PRINT("Error: Create ssl failed.");
        return 0;
    }
    SSL_set_fd(ssl, clientSocketId);

    int32_t retCode = 0;
    do {
        int32_t ret = SSL_accept(ssl);
        if(ret != 1) {
            SERVER_PRINT("Error: SSL accept failed. ret = %d", ret);
            retCode = -1;
            break;
        }
        uint32_t resLen = strlen(S_NetParam_.respondContent.c_str());
        ret = SSL_write(ssl, S_NetParam_.respondContent.c_str(), resLen);
        if(ret < 0) {
            SERVER_PRINT("Error: SSL write respondContent failed. ret = %d", ret);
            SSL_shutdown(ssl);
            retCode = -1;
            break;
        }
        SSL_shutdown(ssl);
    }while(0);
    SSL_free(ssl);
    return 0;
}

int32_t SearchPkgServer::Close()
{
    if(S_NetEnv_.socketId != -1) {
        close(S_NetEnv_.socketId);
    }
    if(S_NetEnv_.sslctx != NULL) {
        SSL_CTX_free(S_NetEnv_.sslctx);
    }
    return 0;
}

}
}

        7.4 search_pkg_server_main.cpp文件:  

#include "search_pkg_server.h"

#include <stdio.h>
#include <chrono>
#include <thread>

using namespace OHOS::UpdateEngine;

int32_t main(int32_t argc, char *argv[])
{
    if(argc != 1) {
        SERVER_PRINT("Usage: ./SearchPkgServer");
        return 0;
    }

    if(OHOS::DelayedSingleton<SearchPkgServer>::GetInstance()->Init() != 0) {
        SERVER_PRINT("Error: Initialize Server failed.");
        return 0;
    }

    if(OHOS::DelayedSingleton<SearchPkgServer>::GetInstance()->Open() != 0) {
        SERVER_PRINT("Error: Open Server failed.");
        return 0;
    }

    while(1) {
        if(OHOS::DelayedSingleton<SearchPkgServer>::GetInstance()->MainLoop() != 0) {
            SERVER_PRINT("Error: MainLoop failed.");
            return 0;
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(DEFAULT_SLEEP));
    }
    SERVER_PRINT("Info: Exit MainLoop Success.");

    if(OHOS::DelayedSingleton<SearchPkgServer>::GetInstance()->Close() != 0) {
        SERVER_PRINT("Error: Close Server failed.");
        return 0;
    }
    SERVER_PRINT("Info: Close Server success.");
    
    return 0;
}

        7.5 BUILD.gn文件

import("//build/ohos.gni")

ohos_executable("SearchPkgServer") {
    sources = [
        "//base/update/updateservice/search_pkg_server/src/search_pkg_server.cpp",
        "//base/update/updateservice/search_pkg_server/src/search_pkg_server_main.cpp",
    ]

    include_dirs = [
        "//base/update/updateservice/search_pkg_server/include",
        "//third_party/openssl/include",
    ]

    deps = [
        "//base/update/updater/services/log:libupdaterlog",
        "//third_party/bounds_checking_function:libsec_static",
        "//third_party/openssl:crypto_source",
        "//third_party/openssl:ssl_source",
    ]

    external_deps = [
        "c_utils:utils",
    ]

    part_name = "update_service"
}

 

 

Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐