FreeRDP
Loading...
Searching...
No Matches
UdpAppender.c
1
21#include <winpr/config.h>
22
23#include <winpr/crt.h>
24#include <winpr/environment.h>
25#include <winpr/winsock.h>
26
27#include "wlog.h"
28
29typedef struct
30{
31 wLogAppender common;
32 char* host;
33 struct sockaddr targetAddr;
34 int targetAddrLen;
35 SOCKET sock;
36} wLogUdpAppender;
37
38static BOOL WLog_UdpAppender_Open(WINPR_ATTR_UNUSED wLog* log, wLogAppender* appender)
39{
40 wLogUdpAppender* udpAppender = nullptr;
41 char addressString[256] = WINPR_C_ARRAY_INIT;
42 struct addrinfo hints = WINPR_C_ARRAY_INIT;
43 struct addrinfo* result = WINPR_C_ARRAY_INIT;
44 int status = 0;
45 char* colonPos = nullptr;
46
47 if (!appender)
48 return FALSE;
49
50 udpAppender = (wLogUdpAppender*)appender;
51
52 if (udpAppender->targetAddrLen) /* already opened */
53 return TRUE;
54
55 colonPos = strchr(udpAppender->host, ':');
56
57 if (!colonPos)
58 return FALSE;
59
60 const size_t addrLen = WINPR_ASSERTING_INT_CAST(size_t, (colonPos - udpAppender->host));
61 memcpy(addressString, udpAppender->host, addrLen);
62 addressString[addrLen] = '\0';
63 hints.ai_family = AF_INET;
64 hints.ai_socktype = SOCK_DGRAM;
65 status = getaddrinfo(addressString, colonPos + 1, &hints, &result);
66
67 if (status != 0)
68 return FALSE;
69
70 if (result->ai_addrlen > sizeof(udpAppender->targetAddr))
71 {
72 freeaddrinfo(result);
73 return FALSE;
74 }
75
76 memcpy(&udpAppender->targetAddr, result->ai_addr, result->ai_addrlen);
77 udpAppender->targetAddrLen = (int)result->ai_addrlen;
78 freeaddrinfo(result);
79 return TRUE;
80}
81
82static BOOL WLog_UdpAppender_Close(wLog* log, wLogAppender* appender)
83{
84 return !(!log || !appender);
85}
86
87static BOOL WLog_UdpAppender_WriteMessage(wLog* log, wLogAppender* appender,
88 const wLogMessage* cmessage)
89{
90 if (!log || !appender || !cmessage)
91 return FALSE;
92
93 wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
94
95 char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
96 WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix, sizeof(prefix));
97
98 BOOL res = TRUE;
99 if (_sendto(udpAppender->sock, prefix, (int)strnlen(prefix, ARRAYSIZE(prefix)), 0,
100 &udpAppender->targetAddr, udpAppender->targetAddrLen) < 0)
101 res = FALSE;
102 if (_sendto(udpAppender->sock, cmessage->TextString,
103 (int)strnlen(cmessage->TextString, INT_MAX), 0, &udpAppender->targetAddr,
104 udpAppender->targetAddrLen) < 0)
105 res = FALSE;
106 if (_sendto(udpAppender->sock, "\n", 1, 0, &udpAppender->targetAddr,
107 udpAppender->targetAddrLen) < 0)
108 res = FALSE;
109 return res;
110}
111
112static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
113 const wLogMessage* message)
114{
115 return !(!log || !appender || !message);
116}
117
118static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
119 const wLogMessage* message)
120{
121 return !(!log || !appender || !message);
122}
123
124static BOOL WLog_UdpAppender_Set(wLogAppender* appender, const char* setting, void* value)
125{
126 const char target[] = "target";
127 wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
128
129 /* Just check the value string is not empty */
130 if (!value || (strnlen(value, 2) == 0))
131 return FALSE;
132
133 if (strncmp(target, setting, sizeof(target)) != 0)
134 return FALSE;
135
136 udpAppender->targetAddrLen = 0;
137
138 if (udpAppender->host)
139 free(udpAppender->host);
140
141 udpAppender->host = _strdup((const char*)value);
142 return (udpAppender->host != nullptr) && WLog_UdpAppender_Open(nullptr, appender);
143}
144
145static void WLog_UdpAppender_Free(wLogAppender* appender)
146{
147 wLogUdpAppender* udpAppender = nullptr;
148
149 if (appender)
150 {
151 udpAppender = (wLogUdpAppender*)appender;
152
153 if (udpAppender->sock != INVALID_SOCKET)
154 {
155 closesocket(udpAppender->sock);
156 udpAppender->sock = INVALID_SOCKET;
157 }
158
159 free(udpAppender->host);
160 free(udpAppender);
161 }
162}
163
164wLogAppender* WLog_UdpAppender_New(wLog* log)
165{
166 DWORD nSize = 0;
167 LPCSTR name = nullptr;
168 wLogUdpAppender* appender = (wLogUdpAppender*)calloc(1, sizeof(wLogUdpAppender));
169
170 if (!appender)
171 return nullptr;
172
173 appender->common.Type = WLOG_APPENDER_UDP;
174 appender->common.Open = WLog_UdpAppender_Open;
175 appender->common.Close = WLog_UdpAppender_Close;
176 appender->common.WriteMessage = WLog_UdpAppender_WriteMessage;
177 appender->common.WriteDataMessage = WLog_UdpAppender_WriteDataMessage;
178 appender->common.WriteImageMessage = WLog_UdpAppender_WriteImageMessage;
179 appender->common.Free = WLog_UdpAppender_Free;
180 appender->common.Set = WLog_UdpAppender_Set;
181 appender->sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
182
183 if (appender->sock == INVALID_SOCKET)
184 goto error_sock;
185
186 name = "WLOG_UDP_TARGET";
187 nSize = GetEnvironmentVariableA(name, nullptr, 0);
188
189 if (nSize)
190 {
191 appender->host = (LPSTR)malloc(nSize);
192
193 if (!appender->host)
194 goto error_open;
195
196 if (GetEnvironmentVariableA(name, appender->host, nSize) != nSize - 1)
197 goto error_open;
198
199 if (!WLog_UdpAppender_Open(log, (wLogAppender*)appender))
200 goto error_open;
201 }
202 else
203 {
204 appender->host = _strdup("127.0.0.1:20000");
205
206 if (!appender->host)
207 goto error_open;
208 }
209
210 return &appender->common;
211error_open:
212 free(appender->host);
213 closesocket(appender->sock);
214error_sock:
215 free(appender);
216 return nullptr;
217}