summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/utils/wlog/UdpAppender.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--winpr/libwinpr/utils/wlog/UdpAppender.c222
1 files changed, 222 insertions, 0 deletions
diff --git a/winpr/libwinpr/utils/wlog/UdpAppender.c b/winpr/libwinpr/utils/wlog/UdpAppender.c
new file mode 100644
index 0000000..19501dc
--- /dev/null
+++ b/winpr/libwinpr/utils/wlog/UdpAppender.c
@@ -0,0 +1,222 @@
+/**
+ * WinPR: Windows Portable Runtime
+ * WinPR Logger
+ *
+ * Copyright © 2015 Thincast Technologies GmbH
+ * Copyright © 2015 David FORT <contact@hardening-consulting.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <winpr/config.h>
+
+#include <winpr/crt.h>
+#include <winpr/environment.h>
+#include <winpr/winsock.h>
+
+#include "wlog.h"
+
+typedef struct
+{
+ WLOG_APPENDER_COMMON();
+ char* host;
+ struct sockaddr targetAddr;
+ int targetAddrLen;
+ SOCKET sock;
+} wLogUdpAppender;
+
+static BOOL WLog_UdpAppender_Open(wLog* log, wLogAppender* appender)
+{
+ wLogUdpAppender* udpAppender = NULL;
+ char addressString[256] = { 0 };
+ struct addrinfo hints = { 0 };
+ struct addrinfo* result = { 0 };
+ int status = 0;
+ size_t addrLen = 0;
+ char* colonPos = NULL;
+
+ if (!appender)
+ return FALSE;
+
+ udpAppender = (wLogUdpAppender*)appender;
+
+ if (udpAppender->targetAddrLen) /* already opened */
+ return TRUE;
+
+ colonPos = strchr(udpAppender->host, ':');
+
+ if (!colonPos)
+ return FALSE;
+
+ addrLen = (colonPos - udpAppender->host);
+ memcpy(addressString, udpAppender->host, addrLen);
+ addressString[addrLen] = '\0';
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+ status = getaddrinfo(addressString, colonPos + 1, &hints, &result);
+
+ if (status != 0)
+ return FALSE;
+
+ if (result->ai_addrlen > sizeof(udpAppender->targetAddr))
+ {
+ freeaddrinfo(result);
+ return FALSE;
+ }
+
+ memcpy(&udpAppender->targetAddr, result->ai_addr, result->ai_addrlen);
+ udpAppender->targetAddrLen = (int)result->ai_addrlen;
+ freeaddrinfo(result);
+ return TRUE;
+}
+
+static BOOL WLog_UdpAppender_Close(wLog* log, wLogAppender* appender)
+{
+ if (!log || !appender)
+ return FALSE;
+
+ return TRUE;
+}
+
+static BOOL WLog_UdpAppender_WriteMessage(wLog* log, wLogAppender* appender, wLogMessage* message)
+{
+ char prefix[WLOG_MAX_PREFIX_SIZE] = { 0 };
+ wLogUdpAppender* udpAppender = NULL;
+
+ if (!log || !appender || !message)
+ return FALSE;
+
+ udpAppender = (wLogUdpAppender*)appender;
+ message->PrefixString = prefix;
+ WLog_Layout_GetMessagePrefix(log, appender->Layout, message);
+ _sendto(udpAppender->sock, message->PrefixString, (int)strnlen(message->PrefixString, INT_MAX),
+ 0, &udpAppender->targetAddr, udpAppender->targetAddrLen);
+ _sendto(udpAppender->sock, message->TextString, (int)strnlen(message->TextString, INT_MAX), 0,
+ &udpAppender->targetAddr, udpAppender->targetAddrLen);
+ _sendto(udpAppender->sock, "\n", 1, 0, &udpAppender->targetAddr, udpAppender->targetAddrLen);
+ return TRUE;
+}
+
+static BOOL WLog_UdpAppender_WriteDataMessage(wLog* log, wLogAppender* appender,
+ wLogMessage* message)
+{
+ if (!log || !appender || !message)
+ return FALSE;
+
+ return TRUE;
+}
+
+static BOOL WLog_UdpAppender_WriteImageMessage(wLog* log, wLogAppender* appender,
+ wLogMessage* message)
+{
+ if (!log || !appender || !message)
+ return FALSE;
+
+ return TRUE;
+}
+
+static BOOL WLog_UdpAppender_Set(wLogAppender* appender, const char* setting, void* value)
+{
+ const char target[] = "target";
+ wLogUdpAppender* udpAppender = (wLogUdpAppender*)appender;
+
+ /* Just check the value string is not empty */
+ if (!value || (strnlen(value, 2) == 0))
+ return FALSE;
+
+ if (strncmp(target, setting, sizeof(target)))
+ return FALSE;
+
+ udpAppender->targetAddrLen = 0;
+
+ if (udpAppender->host)
+ free(udpAppender->host);
+
+ udpAppender->host = _strdup((const char*)value);
+ return (udpAppender->host != NULL) && WLog_UdpAppender_Open(NULL, appender);
+}
+
+static void WLog_UdpAppender_Free(wLogAppender* appender)
+{
+ wLogUdpAppender* udpAppender = NULL;
+
+ if (appender)
+ {
+ udpAppender = (wLogUdpAppender*)appender;
+
+ if (udpAppender->sock != INVALID_SOCKET)
+ {
+ closesocket(udpAppender->sock);
+ udpAppender->sock = INVALID_SOCKET;
+ }
+
+ free(udpAppender->host);
+ free(udpAppender);
+ }
+}
+
+wLogAppender* WLog_UdpAppender_New(wLog* log)
+{
+ wLogUdpAppender* appender = NULL;
+ DWORD nSize = 0;
+ LPCSTR name = NULL;
+ appender = (wLogUdpAppender*)calloc(1, sizeof(wLogUdpAppender));
+
+ if (!appender)
+ return NULL;
+
+ appender->Type = WLOG_APPENDER_UDP;
+ appender->Open = WLog_UdpAppender_Open;
+ appender->Close = WLog_UdpAppender_Close;
+ appender->WriteMessage = WLog_UdpAppender_WriteMessage;
+ appender->WriteDataMessage = WLog_UdpAppender_WriteDataMessage;
+ appender->WriteImageMessage = WLog_UdpAppender_WriteImageMessage;
+ appender->Free = WLog_UdpAppender_Free;
+ appender->Set = WLog_UdpAppender_Set;
+ appender->sock = _socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+
+ if (appender->sock == INVALID_SOCKET)
+ goto error_sock;
+
+ name = "WLOG_UDP_TARGET";
+ nSize = GetEnvironmentVariableA(name, NULL, 0);
+
+ if (nSize)
+ {
+ appender->host = (LPSTR)malloc(nSize);
+
+ if (!appender->host)
+ goto error_open;
+
+ if (GetEnvironmentVariableA(name, appender->host, nSize) != nSize - 1)
+ goto error_open;
+
+ if (!WLog_UdpAppender_Open(log, (wLogAppender*)appender))
+ goto error_open;
+ }
+ else
+ {
+ appender->host = _strdup("127.0.0.1:20000");
+
+ if (!appender->host)
+ goto error_open;
+ }
+
+ return (wLogAppender*)appender;
+error_open:
+ free(appender->host);
+ closesocket(appender->sock);
+error_sock:
+ free(appender);
+ return NULL;
+}