From 684db035783f0f98543c984fe6197d7ae96c85d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 8 Oct 2013 23:18:59 -0400 Subject: [PATCH] libwinpr-utils: start implement wlog packet appender --- winpr/include/winpr/wlog.h | 25 +- winpr/libwinpr/utils/CMakeLists.txt | 2 + winpr/libwinpr/utils/wlog/ConsoleAppender.c | 28 +++ winpr/libwinpr/utils/wlog/Message.h | 2 + winpr/libwinpr/utils/wlog/PacketMessage.c | 238 ++++++++++++++++++++ winpr/libwinpr/utils/wlog/PacketMessage.h | 82 +++++++ winpr/libwinpr/utils/wlog/wlog.c | 31 ++- 7 files changed, 402 insertions(+), 6 deletions(-) create mode 100644 winpr/libwinpr/utils/wlog/PacketMessage.c create mode 100644 winpr/libwinpr/utils/wlog/PacketMessage.h diff --git a/winpr/include/winpr/wlog.h b/winpr/include/winpr/wlog.h index 7fc82ee7e..29a9e5a44 100644 --- a/winpr/include/winpr/wlog.h +++ b/winpr/include/winpr/wlog.h @@ -56,6 +56,7 @@ typedef struct _wLogAppender wLogAppender; #define WLOG_MESSAGE_TEXT 0 #define WLOG_MESSAGE_DATA 1 #define WLOG_MESSAGE_IMAGE 2 +#define WLOG_MESSAGE_PACKET 3 struct _wLogMessage { @@ -109,17 +110,23 @@ typedef int (*WLOG_APPENDER_CLOSE_FN)(wLog* log, wLogAppender* appender); typedef int (*WLOG_APPENDER_WRITE_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message); typedef int (*WLOG_APPENDER_WRITE_DATA_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message); typedef int (*WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message); +typedef int (*WLOG_APPENDER_WRITE_PACKET_MESSAGE_FN)(wLog* log, wLogAppender* appender, wLogMessage* message); #define WLOG_APPENDER_COMMON() \ DWORD Type; \ DWORD State; \ wLogLayout* Layout; \ CRITICAL_SECTION lock; \ + void* TextMessageContext; \ + void* DataMessageContext; \ + void* ImageMessageContext; \ + void* PacketMessageContext; \ WLOG_APPENDER_OPEN_FN Open; \ WLOG_APPENDER_CLOSE_FN Close; \ WLOG_APPENDER_WRITE_MESSAGE_FN WriteMessage; \ WLOG_APPENDER_WRITE_DATA_MESSAGE_FN WriteDataMessage; \ - WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN WriteImageMessage + WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN WriteImageMessage; \ + WLOG_APPENDER_WRITE_PACKET_MESSAGE_FN WritePacketMessage struct _wLogAppender { @@ -193,6 +200,18 @@ WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); WLog_PrintMessage(_log, &(_log_message), ## __VA_ARGS__ ); \ } +#define WLog_Data(_log, _log_level, ...) \ + if (_log_level >= _log->Level) { \ + wLogMessage _log_message; \ + _log_message.Type = WLOG_MESSAGE_DATA; \ + _log_message.Level = _log_level; \ + _log_message.FormatString = NULL; \ + _log_message.LineNumber = __LINE__; \ + _log_message.FileName = __FILE__; \ + _log_message.FunctionName = __FUNCTION__; \ + WLog_PrintMessage(_log, &(_log_message), ## __VA_ARGS__ ); \ + } + #define WLog_Image(_log, _log_level, ...) \ if (_log_level >= _log->Level) { \ wLogMessage _log_message; \ @@ -205,10 +224,10 @@ WINPR_API void WLog_PrintMessage(wLog* log, wLogMessage* message, ...); WLog_PrintMessage(_log, &(_log_message), ## __VA_ARGS__ ); \ } -#define WLog_Data(_log, _log_level, ...) \ +#define WLog_Packet(_log, _log_level, ...) \ if (_log_level >= _log->Level) { \ wLogMessage _log_message; \ - _log_message.Type = WLOG_MESSAGE_DATA; \ + _log_message.Type = WLOG_MESSAGE_PACKET; \ _log_message.Level = _log_level; \ _log_message.FormatString = NULL; \ _log_message.LineNumber = __LINE__; \ diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index 355514564..fd9f95398 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -61,6 +61,8 @@ set(${MODULE_PREFIX}_WLOG_SRCS wlog/DataMessage.h wlog/ImageMessage.c wlog/ImageMessage.h + wlog/PacketMessage.c + wlog/PacketMessage.h wlog/Appender.c wlog/Appender.h wlog/FileAppender.c diff --git a/winpr/libwinpr/utils/wlog/ConsoleAppender.c b/winpr/libwinpr/utils/wlog/ConsoleAppender.c index f3c4ecdc0..ec7163cff 100644 --- a/winpr/libwinpr/utils/wlog/ConsoleAppender.c +++ b/winpr/libwinpr/utils/wlog/ConsoleAppender.c @@ -116,6 +116,27 @@ int WLog_ConsoleAppender_WriteImageMessage(wLog* log, wLogConsoleAppender* appen return ImageId; } +static int g_PacketId = 0; + +int WLog_ConsoleAppender_WritePacketMessage(wLog* log, wLogConsoleAppender* appender, wLogMessage* message) +{ + int PacketId; + char* FullFileName; + + PacketId = g_PacketId++; + + if (!appender->PacketMessageContext) + { + FullFileName = WLog_Message_GetOutputFileName(PacketId, "pcap"); + appender->PacketMessageContext = (void*) Pcap_Open(FullFileName, TRUE); + free(FullFileName); + } + + WLog_PacketMessage_Write((wPcap*) appender->PacketMessageContext, message->Data, message->Length, 0); + + return PacketId; +} + wLogConsoleAppender* WLog_ConsoleAppender_New(wLog* log) { wLogConsoleAppender* ConsoleAppender; @@ -137,6 +158,8 @@ wLogConsoleAppender* WLog_ConsoleAppender_New(wLog* log) (WLOG_APPENDER_WRITE_DATA_MESSAGE_FN) WLog_ConsoleAppender_WriteDataMessage; ConsoleAppender->WriteImageMessage = (WLOG_APPENDER_WRITE_IMAGE_MESSAGE_FN) WLog_ConsoleAppender_WriteImageMessage; + ConsoleAppender->WritePacketMessage = + (WLOG_APPENDER_WRITE_PACKET_MESSAGE_FN) WLog_ConsoleAppender_WritePacketMessage; ConsoleAppender->outputStream = WLOG_CONSOLE_STDOUT; } @@ -148,6 +171,11 @@ void WLog_ConsoleAppender_Free(wLog* log, wLogConsoleAppender* appender) { if (appender) { + if (appender->PacketMessageContext) + { + Pcap_Close((wPcap*) appender->PacketMessageContext); + } + free(appender); } } diff --git a/winpr/libwinpr/utils/wlog/Message.h b/winpr/libwinpr/utils/wlog/Message.h index 2c90216bd..4ad0227c4 100644 --- a/winpr/libwinpr/utils/wlog/Message.h +++ b/winpr/libwinpr/utils/wlog/Message.h @@ -24,8 +24,10 @@ #include "wlog/wlog.h" +#include "wlog/TextMessage.h" #include "wlog/DataMessage.h" #include "wlog/ImageMessage.h" +#include "wlog/PacketMessage.h" char* WLog_Message_GetOutputFileName(int id, const char* ext); diff --git a/winpr/libwinpr/utils/wlog/PacketMessage.c b/winpr/libwinpr/utils/wlog/PacketMessage.c new file mode 100644 index 000000000..a57126350 --- /dev/null +++ b/winpr/libwinpr/utils/wlog/PacketMessage.c @@ -0,0 +1,238 @@ +/** + * WinPR: Windows Portable Runtime + * WinPR Logger + * + * Copyright 2013 Marc-Andre Moreau + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "wlog/PacketMessage.h" + +#include + +#ifndef _WIN32 +#include +#else +#include +#include +#include + +static int gettimeofday(struct timeval* tp, void* tz) +{ + struct _timeb timebuffer; + _ftime(&timebuffer); + tp->tv_sec = (long) timebuffer.time; + tp->tv_usec = timebuffer.millitm * 1000; + return 0; +} +#endif + +void Pcap_Read_Header(wPcap* pcap, wPcapHeader* header) +{ + fread((void*) header, sizeof(wPcapHeader), 1, pcap->fp); +} + +void Pcap_Write_Header(wPcap* pcap, wPcapHeader* header) +{ + fwrite((void*) header, sizeof(wPcapHeader), 1, pcap->fp); +} + +void Pcap_Read_RecordHeader(wPcap* pcap, wPcapRecordHeader* record) +{ + fread((void*) record, sizeof(wPcapRecordHeader), 1, pcap->fp); +} + +void Pcap_Write_RecordHeader(wPcap* pcap, wPcapRecordHeader* record) +{ + fwrite((void*) record, sizeof(wPcapRecordHeader), 1, pcap->fp); +} + +void Pcap_Read_Record(wPcap* pcap, wPcapRecord* record) +{ + Pcap_Read_RecordHeader(pcap, &record->header); + record->length = record->header.incl_len; + record->data = malloc(record->length); + fread(record->data, record->length, 1, pcap->fp); +} + +void Pcap_Write_Record(wPcap* pcap, wPcapRecord* record) +{ + Pcap_Write_RecordHeader(pcap, &record->header); + fwrite(record->data, record->length, 1, pcap->fp); +} + +void Pcap_Add_Record(wPcap* pcap, void* data, UINT32 length) +{ + wPcapRecord* record; + struct timeval tp; + + if (!pcap->tail) + { + pcap->tail = (wPcapRecord*) malloc(sizeof(wPcapRecord)); + ZeroMemory(pcap->tail, sizeof(wPcapRecord)); + + pcap->head = pcap->tail; + pcap->record = pcap->head; + record = pcap->tail; + } + else + { + record = (wPcapRecord*) malloc(sizeof(wPcapRecord)); + ZeroMemory(record, sizeof(wPcapRecord)); + + pcap->tail->next = record; + pcap->tail = record; + } + + if (!pcap->record) + pcap->record = record; + + record->data = data; + record->length = length; + record->header.incl_len = length; + record->header.orig_len = length; + + gettimeofday(&tp, 0); + record->header.ts_sec = tp.tv_sec; + record->header.ts_usec = tp.tv_usec; +} + +BOOL Pcap_HasNext_Record(wPcap* pcap) +{ + if (pcap->file_size - (ftell(pcap->fp)) <= 16) + return FALSE; + + return TRUE; +} + +BOOL Pcap_GetNext_RecordHeader(wPcap* pcap, wPcapRecord* record) +{ + if (Pcap_HasNext_Record(pcap) != TRUE) + return FALSE; + + Pcap_Read_RecordHeader(pcap, &record->header); + record->length = record->header.incl_len; + + return TRUE; +} + +BOOL Pcap_GetNext_RecordContent(wPcap* pcap, wPcapRecord* record) +{ + fread(record->data, record->length, 1, pcap->fp); + return TRUE; +} + +BOOL Pcap_GetNext_Record(wPcap* pcap, wPcapRecord* record) +{ + if (Pcap_HasNext_Record(pcap) != TRUE) + return FALSE; + + Pcap_Read_Record(pcap, record); + + return TRUE; +} + +wPcap* Pcap_Open(char* name, BOOL write) +{ + wPcap* pcap; + + FILE* pcap_fp = fopen(name, write ? "w+b" : "rb"); + + if (!pcap_fp) + { + perror("opening pcap file"); + return NULL; + } + + pcap = (wPcap*) malloc(sizeof(wPcap)); + + if (pcap) + { + ZeroMemory(pcap, sizeof(wPcap)); + + pcap->name = name; + pcap->write = write; + pcap->record_count = 0; + pcap->fp = pcap_fp; + + if (write) + { + pcap->header.magic_number = PCAP_MAGIC_NUMBER; + pcap->header.version_major = 2; + pcap->header.version_minor = 4; + pcap->header.thiszone = 0; + pcap->header.sigfigs = 0; + pcap->header.snaplen = 0xFFFFFFFF; + pcap->header.network = 0; + Pcap_Write_Header(pcap, &pcap->header); + } + else + { + fseek(pcap->fp, 0, SEEK_END); + pcap->file_size = (int) ftell(pcap->fp); + fseek(pcap->fp, 0, SEEK_SET); + Pcap_Read_Header(pcap, &pcap->header); + } + } + + return pcap; +} + +void Pcap_Flush(wPcap* pcap) +{ + while (pcap->record) + { + Pcap_Write_Record(pcap, pcap->record); + pcap->record = pcap->record->next; + } + + if (pcap->fp) + fflush(pcap->fp); +} + +void Pcap_Close(wPcap* pcap) +{ + Pcap_Flush(pcap); + + if (pcap->fp) + fclose(pcap->fp); + + free(pcap); +} + +int WLog_PacketMessage_Write(wPcap* pcap, void* data, DWORD length, DWORD flags) +{ + struct timeval tp; + wPcapRecord record; + + record.data = data; + record.length = length; + record.next = NULL; + record.header.incl_len = length; + record.header.orig_len = length; + + gettimeofday(&tp, 0); + record.header.ts_sec = tp.tv_sec; + record.header.ts_usec = tp.tv_usec; + + Pcap_Write_Record(pcap, &record); + + return 0; +} diff --git a/winpr/libwinpr/utils/wlog/PacketMessage.h b/winpr/libwinpr/utils/wlog/PacketMessage.h new file mode 100644 index 000000000..ca478cb83 --- /dev/null +++ b/winpr/libwinpr/utils/wlog/PacketMessage.h @@ -0,0 +1,82 @@ +/** + * WinPR: Windows Portable Runtime + * WinPR Logger + * + * Copyright 2013 Marc-Andre Moreau + * + * 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. + */ + +#ifndef WINPR_WLOG_PACKET_MESSAGE_PRIVATE_H +#define WINPR_WLOG_PACKET_MESSAGE_PRIVATE_H + +#include + +#include "wlog/wlog.h" + +#define PCAP_MAGIC_NUMBER 0xA1B2C3D4 + +struct _wPcapHeader +{ + UINT32 magic_number; /* magic number */ + UINT16 version_major; /* major version number */ + UINT16 version_minor; /* minor version number */ + INT32 thiszone; /* GMT to local correction */ + UINT32 sigfigs; /* accuracy of timestamps */ + UINT32 snaplen; /* max length of captured packets, in octets */ + UINT32 network; /* data link type */ +}; +typedef struct _wPcapHeader wPcapHeader; + +struct _wPcapRecordHeader +{ + UINT32 ts_sec; /* timestamp seconds */ + UINT32 ts_usec; /* timestamp microseconds */ + UINT32 incl_len; /* number of octets of packet saved in file */ + UINT32 orig_len; /* actual length of packet */ +}; +typedef struct _wPcapRecordHeader wPcapRecordHeader; + +typedef struct _wPcapRecord wPcapRecord; + +struct _wPcapRecord +{ + wPcapRecordHeader header; + void* data; + UINT32 length; + wPcapRecord* next; +}; + +struct _wPcap +{ + FILE* fp; + char* name; + BOOL write; + int file_size; + int record_count; + wPcapHeader header; + wPcapRecord* head; + wPcapRecord* tail; + wPcapRecord* record; +}; +typedef struct _wPcap wPcap; + +wPcap* Pcap_Open(char* name, BOOL write); +void Pcap_Close(wPcap* pcap); + +void Pcap_Flush(wPcap* pcap); + +int WLog_PacketMessage_Write(wPcap* pcap, void* data, DWORD length, DWORD flags); + +#endif /* WINPR_WLOG_PACKET_MESSAGE_PRIVATE_H */ + diff --git a/winpr/libwinpr/utils/wlog/wlog.c b/winpr/libwinpr/utils/wlog/wlog.c index 0a9ff0516..aa98d8800 100644 --- a/winpr/libwinpr/utils/wlog/wlog.c +++ b/winpr/libwinpr/utils/wlog/wlog.c @@ -79,6 +79,31 @@ int WLog_Write(wLog* log, wLogMessage* message) return status; } +int WLog_WriteData(wLog* log, wLogMessage* message) +{ + int status; + wLogAppender* appender; + + appender = WLog_GetLogAppender(log); + + if (!appender) + return -1; + + if (!appender->State) + WLog_OpenAppender(log); + + if (!appender->WriteDataMessage) + return -1; + + EnterCriticalSection(&appender->lock); + + status = appender->WriteDataMessage(log, appender, message); + + LeaveCriticalSection(&appender->lock); + + return status; +} + int WLog_WriteImage(wLog* log, wLogMessage* message) { int status; @@ -104,7 +129,7 @@ int WLog_WriteImage(wLog* log, wLogMessage* message) return status; } -int WLog_WriteData(wLog* log, wLogMessage* message) +int WLog_WritePacket(wLog* log, wLogMessage* message) { int status; wLogAppender* appender; @@ -117,12 +142,12 @@ int WLog_WriteData(wLog* log, wLogMessage* message) if (!appender->State) WLog_OpenAppender(log); - if (!appender->WriteDataMessage) + if (!appender->WritePacketMessage) return -1; EnterCriticalSection(&appender->lock); - status = appender->WriteDataMessage(log, appender, message); + status = appender->WritePacketMessage(log, appender, message); LeaveCriticalSection(&appender->lock);