21#include <winpr/config.h>
24#include <winpr/environment.h>
25#include <winpr/winsock.h>
33 struct sockaddr targetAddr;
38static BOOL WLog_UdpAppender_Open(WINPR_ATTR_UNUSED wLog* log, wLogAppender* appender)
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;
45 char* colonPos =
nullptr;
50 udpAppender = (wLogUdpAppender*)appender;
52 if (udpAppender->targetAddrLen)
55 colonPos = strchr(udpAppender->host,
':');
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);
70 if (result->ai_addrlen >
sizeof(udpAppender->targetAddr))
76 memcpy(&udpAppender->targetAddr, result->ai_addr, result->ai_addrlen);
77 udpAppender->targetAddrLen = (int)result->ai_addrlen;
82static BOOL WLog_UdpAppender_Close(wLog* log, wLogAppender* appender)
84 return !(!log || !appender);
87static BOOL WLog_UdpAppender_WriteMessage(wLog* log, wLogAppender* appender,
90 if (!log || !appender || !cmessage)
93 wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
95 char prefix[WLOG_MAX_PREFIX_SIZE] = WINPR_C_ARRAY_INIT;
96 WLog_Layout_GetMessagePrefix(log, appender->Layout, cmessage, prefix,
sizeof(prefix));
99 if (_sendto(udpAppender->sock, prefix, (
int)strnlen(prefix, ARRAYSIZE(prefix)), 0,
100 &udpAppender->targetAddr, udpAppender->targetAddrLen) < 0)
102 if (_sendto(udpAppender->sock, cmessage->TextString,
103 (
int)strnlen(cmessage->TextString, INT_MAX), 0, &udpAppender->targetAddr,
104 udpAppender->targetAddrLen) < 0)
106 if (_sendto(udpAppender->sock,
"\n", 1, 0, &udpAppender->targetAddr,
107 udpAppender->targetAddrLen) < 0)
112static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
115 return !(!log || !appender || !message);
118static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
121 return !(!log || !appender || !message);
124static BOOL WLog_UdpAppender_Set(wLogAppender* appender,
const char* setting,
void* value)
126 const char target[] =
"target";
127 wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
130 if (!value || (strnlen(value, 2) == 0))
133 if (strncmp(target, setting,
sizeof(target)) != 0)
136 udpAppender->targetAddrLen = 0;
138 if (udpAppender->host)
139 free(udpAppender->host);
141 udpAppender->host = _strdup((
const char*)value);
142 return (udpAppender->host !=
nullptr) && WLog_UdpAppender_Open(
nullptr, appender);
145static void WLog_UdpAppender_Free(wLogAppender* appender)
147 wLogUdpAppender* udpAppender =
nullptr;
151 udpAppender = (wLogUdpAppender*)appender;
153 if (udpAppender->sock != INVALID_SOCKET)
155 closesocket(udpAppender->sock);
156 udpAppender->sock = INVALID_SOCKET;
159 free(udpAppender->host);
164wLogAppender* WLog_UdpAppender_New(wLog* log)
167 LPCSTR name =
nullptr;
168 wLogUdpAppender* appender = (wLogUdpAppender*)calloc(1,
sizeof(wLogUdpAppender));
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);
183 if (appender->sock == INVALID_SOCKET)
186 name =
"WLOG_UDP_TARGET";
187 nSize = GetEnvironmentVariableA(name,
nullptr, 0);
191 appender->host = (LPSTR)malloc(nSize);
196 if (GetEnvironmentVariableA(name, appender->host, nSize) != nSize - 1)
199 if (!WLog_UdpAppender_Open(log, (wLogAppender*)appender))
204 appender->host = _strdup(
"127.0.0.1:20000");
210 return &appender->common;
212 free(appender->host);
213 closesocket(appender->sock);