11401458bSopenharmony_ci/*
21401458bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
31401458bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
41401458bSopenharmony_ci * you may not use this file except in compliance with the License.
51401458bSopenharmony_ci * You may obtain a copy of the License at
61401458bSopenharmony_ci *
71401458bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
81401458bSopenharmony_ci *
91401458bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
101401458bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
111401458bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121401458bSopenharmony_ci * See the License for the specific language governing permissions and
131401458bSopenharmony_ci * limitations under the License.
141401458bSopenharmony_ci */
151401458bSopenharmony_ci
161401458bSopenharmony_ci#include "hisysevent_easy.h"
171401458bSopenharmony_ci
181401458bSopenharmony_ci#include <stddef.h>
191401458bSopenharmony_ci#include <string.h>
201401458bSopenharmony_ci#include <time.h>
211401458bSopenharmony_ci#include <unistd.h>
221401458bSopenharmony_ci
231401458bSopenharmony_ci#include "easy_def.h"
241401458bSopenharmony_ci#include "easy_event_builder.h"
251401458bSopenharmony_ci#include "easy_socket_writer.h"
261401458bSopenharmony_ci#include "easy_util.h"
271401458bSopenharmony_ci
281401458bSopenharmony_ci#ifdef __cplusplus
291401458bSopenharmony_ciextern "C" {
301401458bSopenharmony_ci#endif
311401458bSopenharmony_ci
321401458bSopenharmony_cistatic const char CUSTOMIZED_PARAM_KEY[] = "DATA";
331401458bSopenharmony_cistatic const int SEC_2_MILLIS = 1000;
341401458bSopenharmony_cistatic const int MILLS_2_NANOS = 1000000;
351401458bSopenharmony_ci
361401458bSopenharmony_cistatic int64_t GetTimestamp()
371401458bSopenharmony_ci{
381401458bSopenharmony_ci    struct timespec tp;
391401458bSopenharmony_ci    clock_gettime(CLOCK_REALTIME, &tp);
401401458bSopenharmony_ci    int64_t time = tp.tv_sec * SEC_2_MILLIS;
411401458bSopenharmony_ci    time += tp.tv_nsec / MILLS_2_NANOS;
421401458bSopenharmony_ci    return time;
431401458bSopenharmony_ci}
441401458bSopenharmony_ci
451401458bSopenharmony_cistatic uint8_t ParseTimeZone(long tz)
461401458bSopenharmony_ci{
471401458bSopenharmony_ci    static long allTimeZones[] = {
481401458bSopenharmony_ci        3600, 7200, 10800, 11880, 14400, 18000, 21600,
491401458bSopenharmony_ci        25200, 28800, 32400, 33480, 36000, 39600, 43200,
501401458bSopenharmony_ci        0, -3600, -7200, -10800, -11880, -14400, 15480,
511401458bSopenharmony_ci        -18000, -19080, -19620, -21600, -22680, -25200, -28800,
521401458bSopenharmony_ci        -30420, -32400, -33480, -36000, -37080, -39600, -43200,
531401458bSopenharmony_ci        -44820, -46800, -50400
541401458bSopenharmony_ci    };
551401458bSopenharmony_ci    uint8_t ret = 14; // 14 is the index of "+0000" in array
561401458bSopenharmony_ci    for (uint8_t index = 0; index < (sizeof(allTimeZones) / sizeof(long)); ++index) {
571401458bSopenharmony_ci        if (allTimeZones[index] == tz) {
581401458bSopenharmony_ci            ret = index;
591401458bSopenharmony_ci            break;
601401458bSopenharmony_ci        }
611401458bSopenharmony_ci    }
621401458bSopenharmony_ci    return ret;
631401458bSopenharmony_ci}
641401458bSopenharmony_ci
651401458bSopenharmony_cistatic int CheckEventType(uint8_t eventType)
661401458bSopenharmony_ci{
671401458bSopenharmony_ci    if ((eventType < EASY_EVENT_TYPE_FAULT) || (eventType > EASY_EVENT_TYPE_BEHAVIOR)) {
681401458bSopenharmony_ci        return ERR_TYPE_INVALID;
691401458bSopenharmony_ci    }
701401458bSopenharmony_ci    return SUCCESS;
711401458bSopenharmony_ci}
721401458bSopenharmony_ci
731401458bSopenharmony_cistatic int InitEventHeader(struct HiSysEventEasyHeader* header, const char* domain, const char* name,
741401458bSopenharmony_ci    const uint8_t eventType)
751401458bSopenharmony_ci{
761401458bSopenharmony_ci    if ((MemoryCopy((uint8_t*)(header->domain), DOMAIN_ARRAY_LEN, (uint8_t*)domain, strlen(domain)) != SUCCESS) ||
771401458bSopenharmony_ci        (MemoryCopy((uint8_t*)(header->name), NAME_ARRAY_LEN, (uint8_t*)name, strlen(name)) != SUCCESS)) {
781401458bSopenharmony_ci        return ERR_MEM_OPT_FAILED;
791401458bSopenharmony_ci    }
801401458bSopenharmony_ci    header->type = eventType - 1; // only 2 bits to store event type
811401458bSopenharmony_ci    header->timestamp = GetTimestamp();
821401458bSopenharmony_ci    tzset();
831401458bSopenharmony_ci    header->timeZone = ParseTimeZone(timezone);
841401458bSopenharmony_ci    header->pid = (uint32_t)getpid();
851401458bSopenharmony_ci    header->tid = (uint32_t)gettid();
861401458bSopenharmony_ci    header->uid = (uint32_t)getuid();
871401458bSopenharmony_ci    header->isTraceOpened = 0; // no need to allocate memory for trace info.
881401458bSopenharmony_ci    return SUCCESS;
891401458bSopenharmony_ci}
901401458bSopenharmony_ci
911401458bSopenharmony_ciint HiSysEventEasyWrite(const char* domain, const char* name, enum HiSysEventEasyType eventType, const char* data)
921401458bSopenharmony_ci{
931401458bSopenharmony_ci    if ((domain == NULL) || (strlen(domain) > MAX_DOMAIN_LENGTH)) {
941401458bSopenharmony_ci        return ERR_DOMAIN_INVALID;
951401458bSopenharmony_ci    }
961401458bSopenharmony_ci    if ((name == NULL) || (strlen(name) > MAX_EVENT_NAME_LENGTH)) {
971401458bSopenharmony_ci        return ERR_NAME_INVALID;
981401458bSopenharmony_ci    }
991401458bSopenharmony_ci    int ret = CheckEventType(eventType);
1001401458bSopenharmony_ci    if (ret != SUCCESS) {
1011401458bSopenharmony_ci        return ret;
1021401458bSopenharmony_ci    }
1031401458bSopenharmony_ci    uint8_t eventBuffer[EVENT_BUFF_LEN] = { 0 };
1041401458bSopenharmony_ci    size_t offset = 0;
1051401458bSopenharmony_ci    // applend block size
1061401458bSopenharmony_ci    *((int32_t*)eventBuffer) = EVENT_BUFF_LEN;
1071401458bSopenharmony_ci    offset += sizeof(int32_t);
1081401458bSopenharmony_ci    // append header, only two bits to store event type in memory
1091401458bSopenharmony_ci    struct HiSysEventEasyHeader header;
1101401458bSopenharmony_ci    ret = MemoryInit((uint8_t*)(&header), sizeof(struct HiSysEventEasyHeader));
1111401458bSopenharmony_ci    if (ret != SUCCESS) {
1121401458bSopenharmony_ci        return ret;
1131401458bSopenharmony_ci    }
1141401458bSopenharmony_ci    ret = InitEventHeader(&header, domain, name, eventType);
1151401458bSopenharmony_ci    if (ret != SUCCESS) {
1161401458bSopenharmony_ci        return ret;
1171401458bSopenharmony_ci    }
1181401458bSopenharmony_ci    ret = AppendHeader(eventBuffer, EVENT_BUFF_LEN, &offset, &header);
1191401458bSopenharmony_ci    if (ret != SUCCESS) {
1201401458bSopenharmony_ci        return ret;
1211401458bSopenharmony_ci    }
1221401458bSopenharmony_ci    // append param count, only one cutomized parameter
1231401458bSopenharmony_ci    if (offset + sizeof(int32_t) > EVENT_BUFF_LEN) {
1241401458bSopenharmony_ci        return ERR_EVENT_BUF_INVALID;
1251401458bSopenharmony_ci    }
1261401458bSopenharmony_ci    *((int32_t*)(eventBuffer + offset)) = 1;
1271401458bSopenharmony_ci    offset += sizeof(int32_t);
1281401458bSopenharmony_ci    ret = AppendStringParam(eventBuffer, EVENT_BUFF_LEN, &offset, CUSTOMIZED_PARAM_KEY, data);
1291401458bSopenharmony_ci    if (ret != SUCCESS) {
1301401458bSopenharmony_ci        return ret;
1311401458bSopenharmony_ci    }
1321401458bSopenharmony_ci    // write event to socket
1331401458bSopenharmony_ci    ret = Write(eventBuffer, EVENT_BUFF_LEN);
1341401458bSopenharmony_ci    if (ret != SUCCESS) {
1351401458bSopenharmony_ci        return ret;
1361401458bSopenharmony_ci    }
1371401458bSopenharmony_ci    return SUCCESS;
1381401458bSopenharmony_ci}
1391401458bSopenharmony_ci
1401401458bSopenharmony_ci#ifdef __cplusplus
1411401458bSopenharmony_ci}
1421401458bSopenharmony_ci#endif