1 krisbash 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 krisbash 1.1 **==============================================================================
23 */
24
25 #include <stdio.h>
26 #include <stddef.h>
27 #include <pthread.h>
28 #include <unistd.h>
29 #include <sys/types.h>
30
31 #include <MI.h>
32 #include <common.h>
33 #include <base/result.h>
34
35 #include "logging.h"
36
37 #if defined(linux)
38 #include <syscall.h>
39 #endif
40
41 #if defined(CONFIG_OS_WINDOWS)
42 # include <windows.h>
43 krisbash 1.1 # include <time.h>
44 #elif defined(CONFIG_POSIX)
45 # include <unistd.h>
46 # include <time.h>
47 # include <sys/time.h>
48 # include <sys/types.h>
49 # include <openssl/ssl.h>
50 # include <openssl/err.h>
51 #endif
52
53 //==============================================================================
54 //
55 // Tables of values used in debugging output
56 //
57 //==============================================================================
58
59 // type for describing enums
60 typedef struct _NameValuePairs
61 {
62 unsigned int Value;
63 const char* Name;
64 krisbash 1.1 } NameValuePairs;
65
66 // names of selector mask flags
67 static const char* SelectorFlagNames[] = { "ADD", "READ", "WRITE", "EXCEPTION", "TIMEOUT", "REMOVE", "DESTORY", "IGNORE_REG_OVERLOAD" };
68
69 // bit numbers
70 static const char* BitNumberNames[32] =
71 {
72 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
73 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
74 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
75 "30", "31"
76 };
77
78 // names of HttpClient statuses
79 static NameValuePairs ClientStatusNames[] =
80 {
81 { 200, "OKAY" }, /* operations was successful */
82 { 408, "TIMEOUT" }, /* operation was not completed within required timeout */
83 { 0, "FAILED" }, /* network error (closed connection, unable to connect, etc.) */
84 { 404, "NOTFOUND" }, /* HTTP status 404 */
85 krisbash 1.1 { 410, "CANCELED" } /* operation was canceled by user */
86 };
87
88 static NameValuePairs NotifyItemTypeNames[] =
89 {
90 { 0, "CONNECT" },
91 { 1, "START_REQUEST" },
92 { 2, "DELETE_HTTP" },
93 { 3, "SET_TIMEOUT" }
94 };
95
96 static NameValuePairs MessageTagNames[] =
97 {
98 { 1, "GetInstanceReqTag" },
99 { 2, "PostInstanceMsgTag" },
100 { 3, "EnumerateInstancesReqTag" },
101 { 4, "PostResultMsgTag" },
102 { 5, "NoOpReqTag" },
103 { 6, "NoOpRspTag" },
104 { 7, "DispResultMsgTag" },
105 { 8, "InvokeReqTag" },
106 krisbash 1.1 { 9, "AssociatorsOfReqTag" },
107 { 10, "ReferencesOfReqTag" },
108 { 11, "SubscribeReqTag" },
109 { 12, "SubscribeResTag" },
110 { 13, "DeleteInstanceReqTag" },
111 { 14, "CreateInstanceReqTag" },
112 { 15, "ModifyInstanceReqTag" },
113 { 16, "BinProtocolNotificationTag" }
114 };
115
116 static NameValuePairs ProtocolEventNames[] =
117 {
118 { 0, "CONNECT" },
119 { 1, "CONNECT_FAILED" },
120 { 2, "DISCONNECT" }
121 };
122
123 //==============================================================================
124 //
125 // Helper function for time
126 //
127 krisbash 1.1 //==============================================================================
128
129 MI_EXPORT MI_Result Time_Now(
130 MI_Uint64* self)
131 {
132 #if defined(CONFIG_OS_WINDOWS)
133 FILETIME ft;
134 ULARGE_INTEGER tmp;
135
136 GetSystemTimeAsFileTime(&ft);
137 tmp.u.LowPart = ft.dwLowDateTime;
138 tmp.u.HighPart = ft.dwHighDateTime;
139 tmp.QuadPart -= 0x19DB1DED53E8000;
140 *self = tmp.QuadPart / (UINT64)10;
141 return MI_RESULT_OK;
142 #else
143 struct timeval tv;
144 struct timezone tz;
145 memset(&tv, 0, sizeof(tv));
146 memset(&tz, 0, sizeof(tz));
147
148 krisbash 1.1 if (gettimeofday(&tv, &tz) != 0)
149 return MI_RESULT_FAILED;
150
151 *self = (MI_Uint64)tv.tv_sec * (MI_Uint64)1000000 + (MI_Uint64)tv.tv_usec;
152 return MI_RESULT_OK;
153 #endif
154 }
155
156 //==============================================================================
157 //
158 // Helper functions for formatting debugging output
159 //
160 //==============================================================================
161
162 // We prefer the LWP thread ID for Linux, but use the pthread ID (the address of errno) for other UNIXes
163 MI_EXPORT unsigned long get_tid()
164 {
165 #if defined(CONFIG_OS_WINDOWS)
166 return (unsigned long)GetCurrentThreadId();
167 #elif defined(linux)
168 return (unsigned long)syscall(SYS_gettid);
169 krisbash 1.1 #else
170 return (unsigned long)pthread_self();
171 #endif
172 }
173
174 static char FmtBuf[4][256];
175 static int WhichFmtBuf = 0;
176
177 static const char* FmtBits(MI_Uint32 Mask, const char* Names[], size_t NumNames)
178 {
179 unsigned int i;
180 char* NamesBuf = FmtBuf[WhichFmtBuf];
181
182 *NamesBuf = '\0';
183 for (i = 0; i < (MI_Uint32)NumNames; i++)
184 {
185 if ((Mask & (1 << i)) != 0)
186 {
187 if (*NamesBuf != '\0')
188 {
189 strcat(NamesBuf, ",");
190 krisbash 1.1 }
191 strcat(NamesBuf, Names[i]);
192 }
193 }
194 if (*NamesBuf == '\0')
195 {
196 strcpy(NamesBuf, "none");
197 }
198 WhichFmtBuf++;
199 WhichFmtBuf &= 3;
200 return NamesBuf;
201 }
202
203 // formatter for enums
204 static const char* FmtEnum(unsigned int Value, NameValuePairs* Pairs, size_t NumNames)
205 {
206 size_t i;
207
208 for (i = 0; i < NumNames; i++)
209 {
210 if (Value == (Pairs + i)->Value)
211 krisbash 1.1 {
212 return (Pairs + i)->Name;
213 }
214 }
215 WhichFmtBuf++;
216 WhichFmtBuf &= 3;
217 return "unknown";
218 }
219
220 //==============================================================================
221 //
222 // Functions that format debugging output
223 //
224 //==============================================================================
225
226 MI_EXPORT const char* selectorflagstr(MI_Uint32 Flags)
227 {
228 return FmtBits((unsigned int)Flags, SelectorFlagNames, sizeof (SelectorFlagNames) / sizeof (const char*));
229 }
230
231 MI_EXPORT const char* bitnumberstr(unsigned long Bits)
232 krisbash 1.1 {
233 return FmtBits((unsigned int)Bits, BitNumberNames, sizeof (BitNumberNames) / sizeof (const char*));
234 }
235
236 MI_EXPORT const char* mistrerror(MI_Result res)
237 {
238 #if defined CONFIG_ENABLE_WCHAR
239 char buf[32];
240 size_t i;
241
242 ZChar* str = Result_ToString(res);
243 for (i = 0; i < 31 && *(str + i) != '\0'; i++, str++)
244 buf[i] = (char)*(str + i);
245 buf[i] = '\0';
246 return buf;
247 #else
248 return Result_ToString(res);
249 #endif
250 }
251
252 MI_EXPORT const char* sslstrerror(unsigned long SslError)
253 krisbash 1.1 {
254 char* buf = FmtBuf[WhichFmtBuf];
255
256 ERR_error_string_n(SslError, buf, 256);
257 WhichFmtBuf++;
258 WhichFmtBuf &= 3;
259 return buf;
260 }
261
262 MI_EXPORT const char* notifyitemtypestr(int NotifyItemType)
263 {
264 return FmtEnum((unsigned int)NotifyItemType, NotifyItemTypeNames, sizeof (NotifyItemTypeNames) / sizeof (NameValuePairs));
265 }
266
267 MI_EXPORT const char* clientstatusstr(int Status)
268 {
269 return FmtEnum((unsigned int)Status, ClientStatusNames, sizeof (ClientStatusNames) / sizeof (NameValuePairs));
270 }
271
272 MI_EXPORT const char* messagetagnamestr(int Tag)
273 {
274 krisbash 1.1 return FmtEnum((unsigned int)Tag, MessageTagNames, sizeof (MessageTagNames) / sizeof (NameValuePairs));
275 }
276
277 MI_EXPORT const char* protocoleventnamestr(int Event)
278 {
279 return FmtEnum((unsigned int)Event, ProtocolEventNames, sizeof (ProtocolEventNames) / sizeof (NameValuePairs));
280 }
281
282 MI_EXPORT const char* FmtTime(MI_Uint64 Time)
283 {
284 char* TmBuf;
285 unsigned long Sec;
286 unsigned long uSec;
287 unsigned long Min;
288 unsigned long Hr;
289
290 if (Time == 0)
291 {
292 return "None";
293 }
294
295 krisbash 1.1 Sec = (unsigned long)(Time / 1000000);
296 uSec = (unsigned long)(Time % 1000000);
297 Min = Sec / 60;
298 Sec -= Min * 60;
299 Hr = Min / 60;
300 Min -= Hr * 60;
301 Hr %= 24;
302 TmBuf = FmtBuf[WhichFmtBuf];
303 sprintf(TmBuf, "%02lu:%02lu:%02lu.%03lu", Hr, Min, Sec, uSec / 1000);
304 WhichFmtBuf++;
305 WhichFmtBuf &= 3;
306 return TmBuf;
307 }
308
309 MI_EXPORT const char* FmtInterval(MI_Sint64 Time)
310 {
311 char* TmBufBase = FmtBuf[WhichFmtBuf];
312 char* TmBuf = TmBufBase;
313 unsigned long Sec;
314 unsigned long uSec;
315 unsigned long Min;
316 krisbash 1.1 unsigned long Hr;
317
318 if (Time < 0)
319 {
320 *TmBuf++ = '-';
321 Time = -Time;
322 }
323 Sec = (unsigned long)(Time / 1000000);
324 uSec = (unsigned long)(Time % 1000000);
325 Min = (unsigned long)Sec / 60;
326 Sec -= Min * 60;
327 Hr = Min / 60;
328 Min -= Hr * 60;
329 Hr %= 60;
330 if (Hr != 0)
331 {
332 sprintf(TmBuf, "%02lu:%02lu:%02lu.%03lu", Hr, Min, Sec, uSec / 1000);
333 }
334 else if (Min != 0)
335 {
336 sprintf(TmBuf, "%02lu:%02lu.%03lu", Min, Sec, uSec / 1000);
337 krisbash 1.1 }
338 else if (Sec == 0 && uSec == 0)
339 {
340 sprintf(TmBuf, "0.0");
341 }
342 else if (Sec != 0 || uSec >= 1000)
343 {
344 sprintf(TmBuf, "%lu.%03lu", Sec, uSec / 1000);
345 }
346 else
347 {
348 sprintf(TmBuf, "%lu.%06lu", Sec, uSec);
349 }
350
351 WhichFmtBuf++;
352 WhichFmtBuf &= 3;
353 return TmBufBase;
354 }
|