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 (void)_sendto(udpAppender->sock, prefix, (int)strnlen(prefix, ARRAYSIZE(prefix)), 0,
99 &udpAppender->targetAddr, udpAppender->targetAddrLen);
100 (void)_sendto(udpAppender->sock, cmessage->TextString,
101 (int)strnlen(cmessage->TextString, INT_MAX), 0, &udpAppender->targetAddr,
102 udpAppender->targetAddrLen);
103 (void)_sendto(udpAppender->sock, "\n", 1, 0, &udpAppender->targetAddr,
104 udpAppender->targetAddrLen);
105 return TRUE;
106}
107
108static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
109 const wLogMessage* message)
110{
111 return !(!log || !appender || !message);
112}
113
114static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
115 const wLogMessage* message)
116{
117 return !(!log || !appender || !message);
118}
119
120static BOOL WLog_UdpAppender_Set(wLogAppender* appender, const char* setting, void* value)
121{
122 const char target[] = "target";
123 wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
124
125 /* Just check the value string is not empty */
126 if (!value || (strnlen(value, 2) == 0))
127 return FALSE;
128
129 if (strncmp(target, setting, sizeof(target)) != 0)
130 return FALSE;
131
132 udpAppender->targetAddrLen = 0;
133
134 if (udpAppender->host)
135 free(udpAppender->host);
136
137 udpAppender->host = _strdup((const char*)value);
138 return (udpAppender->host != nullptr) && WLog_UdpAppender_Open(nullptr, appender);
139}
140
141static void WLog_UdpAppender_Free(wLogAppender* appender)
142{
143 wLogUdpAppender* udpAppender = nullptr;
144
145 if (appender)
146 {
147 udpAppender = (wLogUdpAppender*)appender;
148
149 if (udpAppender->sock != INVALID_SOCKET)
150 {
151 closesocket(udpAppender->sock);
152 udpAppender->sock = INVALID_SOCKET;
153 }
154
155 free(udpAppender->host);
156 free(udpAppender);
157 }
158}
159
160wLogAppender* WLog_UdpAppender_New(wLog* log)
161{
162 DWORD nSize = 0;
163 LPCSTR name = nullptr;
164 wLogUdpAppender* appender = (wLogUdpAppender*)calloc(1, sizeof(wLogUdpAppender));
165
166 if (!appender)
167 return nullptr;
168
169 appender->common.Type = WLOG_APPENDER_UDP;
170 appender->common.Open = WLog_UdpAppender_Open;
171 appender->common.Close = WLog_UdpAppender_Close;
172 appender->common.WriteMessage = WLog_UdpAppender_WriteMessage;
173 appender->common.WriteDataMessage = WLog_UdpAppender_WriteDataMessage;
174 appender->common.WriteImageMessage = WLog_UdpAppender_WriteImageMessage;
175 appender->common.Free = WLog_UdpAppender_Free;
176 appender->common.Set = WLog_UdpAppender_Set;
177 appender->sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
178
179 if (appender->sock == INVALID_SOCKET)
180 goto error_sock;
181
182 name = "WLOG_UDP_TARGET";
183 nSize = GetEnvironmentVariableA(name, nullptr, 0);
184
185 if (nSize)
186 {
187 appender->host = (LPSTR)malloc(nSize);
188
189 if (!appender->host)
190 goto error_open;
191
192 if (GetEnvironmentVariableA(name, appender->host, nSize) != nSize - 1)
193 goto error_open;
194
195 if (!WLog_UdpAppender_Open(log, (wLogAppender*)appender))
196 goto error_open;
197 }
198 else
199 {
200 appender->host = _strdup("127.0.0.1:20000");
201
202 if (!appender->host)
203 goto error_open;
204 }
205
206 return &appender->common;
207error_open:
208 free(appender->host);
209 closesocket(appender->sock);
210error_sock:
211 free(appender);
212 return nullptr;
213}