SysLogd Class for Sending and Receiving SysLogd Events
// December 8th, 2009 // Useful Code
Below is not only the class to create a SysLogd server but also the code to create a console application which will take the SysLogd messages and store them in the Windows Event Log.
//Class
public class SysLogd
{
//DETERMINES WHAT PORT TO RUN ON (DEFAULT IS 514)
private int mPort = 514;
public int Port
{
get
{
return mPort;
}
set
{
mPort = value;
}
}
//USED TO THROW AN EVENT WHEN DATA IS RECEIVED
public delegate void MessageReceived(MessageStruct Message);
private MessageReceived mCallback = null;
//USED TO RUN THE BACKGROUND THREAD READING FOR SYSLOG PACKETS
private System.Threading.Thread mThread;
private bool mRunning = false;
public void StartListening(MessageReceived CallBack)
{
//STORE THE CALLBACK
mCallback = CallBack;
//CREATE A NEW THREAD USING OUR THREADSTART METHOD MAKE SURE ITS A BACKGROUND THREAD SO WHEN WE EXIT IT DOES TO
mThread = new System.Threading.Thread(ThreadStart);
mRunning = true;
mThread.IsBackground = true;
//START LISTENING FOR SYSLOG PACKETS
mThread.Start();
}
public void StopListening()
{
//FLAG OUR RUNNING VARIABLE TO FALSE SO WE WILL STOP LISTENING
mRunning = false;
}
public void SendMessage(MessageStruct Message, string RemoteHost)
{
UdpClient sendSocket = new UdpClient(RemoteHost, this.Port);
byte[] output = System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("<{0}>{1} {2}:{3}", ((int)Message.Pri.Facility *
+ (int)Message.Pri.Severity, Message.TimeStamp.ToString("MMM dd hh:mm:ss"), System.Environment.MachineName, Message.Message));
//MAKE SURE THE FINAL BUFFER IS LESS THEN 1024 BYTES AND IF SO THEN SEND THE DATA
if (output.Length < 1024)
{
sendSocket.Send(output, output.Length);
sendSocket.Close();
}
else
{
throw new InsufficientMemoryException("The data in which you are trying to send does not comply to syslog standards.\nThe total message size must be less then 1024 bytes.");
}
}
private void ThreadStart()
{
Socket ListenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 514);
byte[] buffer = new byte[1024];
//BIND TO THE SOCKET SO WE CAN START READING FOR DATA
ListenSocket.Bind(LocalEndPoint);
while (mRunning)
{
try
{
//READ THE DATA AND IF THERE ISNT ANY DATA THEN WAIT UNTIL THERE IS
EndPoint remoteEP = LocalEndPoint;
int BytesRead = ListenSocket.ReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref remoteEP);
string msg = System.Text.ASCIIEncoding.ASCII.GetString(buffer, 0, BytesRead);
//PARSE THE MESSAGE AND RAISE THE CALL BACK
MessageStruct tmpReturn = new MessageStruct(msg, remoteEP);
mCallback(tmpReturn);
}
catch (Exception e)
{
Console.Write(e.ToString());
}
}
//CLOSE THE SOCKET SINCE WE ARE DONE WITH IT
ListenSocket.Close();
}
public enum FacilityEnum : int
{
Kernel = 0,
User = 1,
Mail = 2,
System = 3,
Security = 4,
Internally = 5,
Printer = 6,
News = 7,
UUCP = 8,
cron = 9,
Security2 = 10,
Ftp = 11,
Ntp = 12,
Audit = 13,
Alert = 14,
Clock2 = 15,
local0 = 16,
local1 = 17,
local2 = 18,
local3 = 19,
local4 = 20,
local5 = 21,
local6 = 22,
local7 = 23,
}
public enum SeverityEnum : int
{
Emergency = 0,
Alert = 1,
Critical = 2,
Error = 3,
Warning = 4,
Notice = 5,
Info = 6,
Debug = 7,
}
public struct PriStruct
{
public FacilityEnum Facility;
public SeverityEnum Severity;
public PriStruct(string strPri)
{
int intPri = Convert.ToInt32(strPri);
int intFacility = intPri >> 3;
int intSeverity = intPri & 0x7;
this.Facility = (FacilityEnum)Enum.Parse(typeof(FacilityEnum),
intFacility.ToString());
this.Severity = (SeverityEnum)Enum.Parse(typeof(SeverityEnum),
intSeverity.ToString());
}
public override string ToString()
{
//EXPORT VALUES TO A VALID PRI STRUCTURE
return string.Format("{0}.{1}", this.Facility, this.Severity);
}
}
public struct MessageStruct
{
public PriStruct Pri { get; set; }
public DateTime TimeStamp { get; set; }
public EndPoint Source { get; set; }
public string Message { get; set; }
public MessageStruct(PriStruct PRI, string Message)
:this()
{
this.Pri = PRI;
this.TimeStamp = DateTime.Now;
this.Source = null;
this.Message = Message;
}
public MessageStruct(string Message, EndPoint RemoteEP)
: this()
{
Regex mRegex = new Regex("<(?<PRI>([0-9]{1,3}))>(?<Message>.*)", RegexOptions.Compiled);
Match tmpMatch = mRegex.Match(Message);
this.Pri = new PriStruct(tmpMatch.Groups["PRI"].Value);
this.Message = tmpMatch.Groups["Message"].Value;
this.TimeStamp = DateTime.Now;
this.Source = RemoteEP;
}
public override string ToString()
{
return string.Format("{0} {1} : {2} : {3} : {4}", Pri.Facility, Pri.Severity, Source.ToString().Split(':')[0], TimeStamp.ToString(), Message);
}
}
}
//Usage
class Program
{
static void Main(string[] args)
{
SysLogd sysLogger = new MCSysLogUtil.SysLogd();
sysLogger.StartListening(MessageReceived);
Console.ReadLine();
}
static void MessageReceived(MCSysLogUtil.SysLogd.MessageStruct Message)
{
EventLog mLog = new EventLog("SysLogd");
EventLogEntryType mType = EventLogEntryType.Information;
switch (Message.Pri.Severity)
{
case SysLogd.SeverityEnum.Alert:
mType = EventLogEntryType.Error;
break;
case SysLogd.SeverityEnum.Critical:
mType = EventLogEntryType.Error;
break;
case SysLogd.SeverityEnum.Debug:
mType = EventLogEntryType.Information;
break;
case SysLogd.SeverityEnum.Emergency:
mType = EventLogEntryType.Error;
break;
case SysLogd.SeverityEnum.Error:
mType = EventLogEntryType.Error;
break;
case SysLogd.SeverityEnum.Info:
mType = EventLogEntryType.Information;
break;
case SysLogd.SeverityEnum.Notice:
mType = EventLogEntryType.Information;
break;
case SysLogd.SeverityEnum.Warning:
mType = EventLogEntryType.Warning;
break;
}
mLog.Source = Message.Source.ToString().Split(':')[0];
mLog.WriteEntry(Message.ToString(), mType);
mLog.Close();
}
}
Leave a Reply
You must be logged in to post a comment.
Michael E. Chancey Jr. Software Engineer Extraordinaire