1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "hisysevent_easy.h"
17 
18 #include <stddef.h>
19 #include <string.h>
20 #include <time.h>
21 #include <unistd.h>
22 
23 #include "easy_def.h"
24 #include "easy_event_builder.h"
25 #include "easy_socket_writer.h"
26 #include "easy_util.h"
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 static const char CUSTOMIZED_PARAM_KEY[] = "DATA";
33 static const int SEC_2_MILLIS = 1000;
34 static const int MILLS_2_NANOS = 1000000;
35 
GetTimestampnull36 static int64_t GetTimestamp()
37 {
38     struct timespec tp;
39     clock_gettime(CLOCK_REALTIME, &tp);
40     int64_t time = tp.tv_sec * SEC_2_MILLIS;
41     time += tp.tv_nsec / MILLS_2_NANOS;
42     return time;
43 }
44 
ParseTimeZone(long tz)45 static uint8_t ParseTimeZone(long tz)
46 {
47     static long allTimeZones[] = {
48         3600, 7200, 10800, 11880, 14400, 18000, 21600,
49         25200, 28800, 32400, 33480, 36000, 39600, 43200,
50         0, -3600, -7200, -10800, -11880, -14400, 15480,
51         -18000, -19080, -19620, -21600, -22680, -25200, -28800,
52         -30420, -32400, -33480, -36000, -37080, -39600, -43200,
53         -44820, -46800, -50400
54     };
55     uint8_t ret = 14; // 14 is the index of "+0000" in array
56     for (uint8_t index = 0; index < (sizeof(allTimeZones) / sizeof(long)); ++index) {
57         if (allTimeZones[index] == tz) {
58             ret = index;
59             break;
60         }
61     }
62     return ret;
63 }
64 
CheckEventType(uint8_t eventType)65 static int CheckEventType(uint8_t eventType)
66 {
67     if ((eventType < EASY_EVENT_TYPE_FAULT) || (eventType > EASY_EVENT_TYPE_BEHAVIOR)) {
68         return ERR_TYPE_INVALID;
69     }
70     return SUCCESS;
71 }
72 
InitEventHeader(struct HiSysEventEasyHeader* header, const char* domain, const char* name, const uint8_t eventType)73 static int InitEventHeader(struct HiSysEventEasyHeader* header, const char* domain, const char* name,
74     const uint8_t eventType)
75 {
76     if ((MemoryCopy((uint8_t*)(header->domain), DOMAIN_ARRAY_LEN, (uint8_t*)domain, strlen(domain)) != SUCCESS) ||
77         (MemoryCopy((uint8_t*)(header->name), NAME_ARRAY_LEN, (uint8_t*)name, strlen(name)) != SUCCESS)) {
78         return ERR_MEM_OPT_FAILED;
79     }
80     header->type = eventType - 1; // only 2 bits to store event type
81     header->timestamp = GetTimestamp();
82     tzset();
83     header->timeZone = ParseTimeZone(timezone);
84     header->pid = (uint32_t)getpid();
85     header->tid = (uint32_t)gettid();
86     header->uid = (uint32_t)getuid();
87     header->isTraceOpened = 0; // no need to allocate memory for trace info.
88     return SUCCESS;
89 }
90 
HiSysEventEasyWrite(const char* domain, const char* name, enum HiSysEventEasyType eventType, const char* data)91 int HiSysEventEasyWrite(const char* domain, const char* name, enum HiSysEventEasyType eventType, const char* data)
92 {
93     if ((domain == NULL) || (strlen(domain) > MAX_DOMAIN_LENGTH)) {
94         return ERR_DOMAIN_INVALID;
95     }
96     if ((name == NULL) || (strlen(name) > MAX_EVENT_NAME_LENGTH)) {
97         return ERR_NAME_INVALID;
98     }
99     int ret = CheckEventType(eventType);
100     if (ret != SUCCESS) {
101         return ret;
102     }
103     uint8_t eventBuffer[EVENT_BUFF_LEN] = { 0 };
104     size_t offset = 0;
105     // applend block size
106     *((int32_t*)eventBuffer) = EVENT_BUFF_LEN;
107     offset += sizeof(int32_t);
108     // append header, only two bits to store event type in memory
109     struct HiSysEventEasyHeader header;
110     ret = MemoryInit((uint8_t*)(&header), sizeof(struct HiSysEventEasyHeader));
111     if (ret != SUCCESS) {
112         return ret;
113     }
114     ret = InitEventHeader(&header, domain, name, eventType);
115     if (ret != SUCCESS) {
116         return ret;
117     }
118     ret = AppendHeader(eventBuffer, EVENT_BUFF_LEN, &offset, &header);
119     if (ret != SUCCESS) {
120         return ret;
121     }
122     // append param count, only one cutomized parameter
123     if (offset + sizeof(int32_t) > EVENT_BUFF_LEN) {
124         return ERR_EVENT_BUF_INVALID;
125     }
126     *((int32_t*)(eventBuffer + offset)) = 1;
127     offset += sizeof(int32_t);
128     ret = AppendStringParam(eventBuffer, EVENT_BUFF_LEN, &offset, CUSTOMIZED_PARAM_KEY, data);
129     if (ret != SUCCESS) {
130         return ret;
131     }
132     // write event to socket
133     ret = Write(eventBuffer, EVENT_BUFF_LEN);
134     if (ret != SUCCESS) {
135         return ret;
136     }
137     return SUCCESS;
138 }
139 
140 #ifdef __cplusplus
141 }
142 #endif