private void RConnPacketHandler(Packet args) { if (args.IsRequest) { var formattedPacket = RecognizedPacket.FormatRequestPacket(args); if (MessageEvents.ContainsKey(args.FirstWord) && MessageEvents[args.FirstWord] != null) { MessageEvents[args.FirstWord](this, formattedPacket); } } else if(args.IsResponse && RequestCallbacks.ContainsKey(args.SequenceNumber)) { Packet request = RequestPackets[args.SequenceNumber]; RequestCallbacks[args.SequenceNumber](this, RecognizedPacket.FormatResponsePacket(request, args)); } //Version .1 we only want player.onChat, admin.say, and admin.yell if (OnChat.IsOnChat(args)) { var chat = new OnChat(args); var message = new ChatMessage { MessageTimeStamp = DateTime.UtcNow, Text = chat.Text, Speaker = chat.SoldierName, MessageType = chat.TargetPlayers.ToString() }; var chatArgs = new ChatEventArgs(message); CommHandler(this, chatArgs); } }
public static Packet BytesToPacket(this byte[] bytes) { if (bytes.Length < Packet.HeaderSize) { return null; } UInt32 sequenceNumber = bytes.BytesToUInt(); UInt32 size = bytes.BytesToUInt(4); UInt32 numWords = bytes.BytesToUInt(8); if (bytes.Length < size) { return null; } var result = new Packet { OrigininatesFromClient = (sequenceNumber & 0x80000000) > 0, IsResponse = (sequenceNumber & 0x40000000) > 0 }; int offset = 12; for (int i = 0; i < numWords; i++) { Word word = bytes.BytesToWord(offset); offset += (int) word.Size + 5; //Include the null terminator and the size int result.Words.Add(word); } return result; }
/// <summary> /// Names the parameters from the specified request packet. /// </summary> /// <param name="packet">The request to be formatted.</param> /// <returns>Name value pairs of the request's parameters.</returns> public static Dictionary<string, string> FormatRequestPacket(Packet packet) { string name = packet.FirstWord; if (packet.IsResponse) { throw new ArgumentException("The specified packet is not a request packet."); } if (ValidRequestFormats.ContainsKey(name)) { PacketFormat format; Dictionary<string, string> parameters = new Dictionary<string, string>(); try { format = ValidRequestFormats[name]; } catch (KeyNotFoundException) { throw new ArgumentException("Somehow, the key wasn't in the ValidRequestFormats dictionary..."); } if (packet.WordCount - 1 > format.Parameters.Count && format.Parameters.Count == 0) { throw new ArgumentException("Unknown variable packet format."); } Stack<string> keys = new Stack<string>(format.Parameters.Select(p => p.Name).Reverse()); Stack<string> words = new Stack<string>(packet.Words.Skip(1).Select(w => new String(w.Content)).Reverse()); while (keys.Count > 0 && words.Count > 0) { string key = keys.Pop(); string word = words.Pop(); if (parameters.ContainsKey(key)) { parameters[key] += word; } else { parameters[key] = word; } //Multi word final parameter if (keys.Count == 0 && words.Count > 0) { keys.Push(key); } } parameters["packet.Name"] = packet.FirstWord; return parameters; } throw new ArgumentException("Unknown request packet."); }
public void RConnPacketHandler(Packet args) { //Detect a socket exception and initiate a reconnect. if (args.FirstWord == "SocketException") { Disconnect(); //Continue to attempt to reconnect unless credentials fail. while (true) { try { Connect(Address, Port, Password); break; } catch (ArgumentException e) { //Bad Password -- we should stop trying to reconnect and let the user handle it. LogUtility.Log(GetType().Name, MethodBase.GetCurrentMethod().Name, e.Message); throw; } catch (Exception e) { //Random connection exceptions; sleep for 2 seconds and try again. LogUtility.Log(GetType().Name, MethodBase.GetCurrentMethod().Name, e.Message); Thread.Sleep(2000); } } return; } if (args.IsRequest) { try { var formattedPacket = RecognizedPacket.FormatRequestPacket(args); if (MessageEvents.ContainsKey(args.FirstWord) && MessageEvents[args.FirstWord] != null) { MessageEvents[args.FirstWord](this, formattedPacket); } } catch (ArgumentException e) { LogUtility.Log(GetType().Name, MethodBase.GetCurrentMethod().Name, e.Message); //TODO: Investigate why FormatRequestPacket is throwing an exception upon server reconnects } } else if (args.IsResponse && RequestCallbacks.ContainsKey(args.SequenceNumber)) { Packet request = RequestPackets[args.SequenceNumber]; if (RequestCallbacks[args.SequenceNumber] != null) { RequestCallbacks[args.SequenceNumber](this, RecognizedPacket.FormatResponsePacket(request, args)); } } }
/// <summary> /// Names the parameters from the specified request packet. /// </summary> /// <param name="packet">The request to be formatted.</param> /// <returns>Name value pairs of the request's parameters.</returns> public static Dictionary<string, string> FormatRequestPacket(Packet packet) { string name = packet.FirstWord; if (packet.IsResponse) { throw new ArgumentException("The specified packet is not a request packet."); } if (ValidRequestFormats.ContainsKey(name)) { Dictionary<string, string> parameters = new Dictionary<string, string>(); PacketFormat format = ValidRequestFormats[name]; // Is this a special packet, using variable length parameters? if (packet.WordCount - 1 > format.Parameters.Count && format.Parameters.Count > 0) { parameters[format.Parameters[0].Name] = ""; foreach (Word word in packet.Words) { parameters[format.Parameters[0].Name] += new string(word.Content); } return parameters; } else if (packet.WordCount - 1 > format.Parameters.Count && format.Parameters.Count == 0) { throw new ArgumentException("Unknown variable packet format."); } for (int i = 1; i < packet.WordCount; i++) { parameters[format.Parameters[i - 1].Name] = new string(packet.Words[i].Content); } parameters["packet.Name"] = packet.FirstWord; return parameters; } throw new ArgumentException("Unknown request packet."); }
public static Packet CreatePacketFromFormattedData(string packetName, Dictionary<string, string> parameters) { if (!ValidRequestFormats.ContainsKey(packetName) || ValidRequestFormats[packetName].MinimumParameterCount > parameters.Count) { throw new ArgumentException("Invalid packet data."); } PacketFormat format = ValidRequestFormats[packetName]; Packet request = new Packet(); request.OrigininatesFromClient = true; request.SequenceNumber = 0; //This will be filled out before being sent. List<Word> words = new List<Word>(); words.Add(new Word(packetName)); for (int i = 0; i < parameters.Count; i++) { words.Add(new Word(parameters[format.Parameters[i].Name])); } request.Words = words; return request; }
private void SendOkResponse(Packet packet) { Sock.Send(new ResponseOk(packet).Emit()); }
private void ReceivePackets() { try { while (Sock.Connected) { Packet packet = ReceivePacket(); if (packet != null) { if (packet.IsRequest) { HandleRequest(packet); } else if (packet.IsResponse) { HandleResponse(packet); } } } } catch (SocketException ex) { LogUtility.Log(GetType().Name, MethodBase.GetCurrentMethod().Name, ex.Message); Packet serverDied = new Packet(); List<Word> words = new List<Word>(); words.Add(new Word("SocketException")); words.Add(new Word(ex.Message)); serverDied.Words = words; if (PacketEvent != null) { //We're going to return from this function anyway which will end the thread; allow a new MessagePump to be started. MessagePump = null; PacketEvent(serverDied); } } }
private void HandleResponse(Packet packet) { if (PacketEvent != null) { PacketEvent(packet); } }
private void HandleRequest(Packet packet) { //All requests we'll be getting for version .1 will be events. SendOkResponse(packet); if (PacketEvent != null) { PacketEvent(packet); } }
public Packet SendRequest(Packet packet) { packet.OrigininatesFromClient = true; packet.IsRequest = true; packet.SequenceNumber = ++SequenceCounter; Sock.Send(packet.Emit()); return packet; }
private void HandleResponse(Packet packet) { PacketEvent(packet); }
private void SendRequest(Packet packet) { packet.OrigininatesFromClient = true; packet.IsRequest = true; packet.SequenceNumber = SequenceCounter++; Sock.Send(packet.Emit()); }
private void SendOkResponse(Packet packet) { packet.OrigininatesFromClient = packet.OrigininatesFromClient; packet.IsRequest = false; packet.SequenceNumber = packet.SequenceNumber; Sock.Send(packet.Emit()); }
/// <summary> /// Names the parameters from the specified response packet. The associated request packet /// is required to differentiate between response formats -- the response name is not unique across /// requests. /// </summary> /// <param name="request">The request which instigated the response.</param> /// <param name="response">The response to be formatted.</param> /// <returns>Name value pairs of the response's parameters</returns> public static Dictionary<string, string> FormatResponsePacket(Packet request, Packet response) { string requestName = request.FirstWord; if (response.IsRequest) { throw new ArgumentException("The specified packet is not a response packet."); } if (!request.IsRequest || request.SequenceNumber != response.SequenceNumber) { throw new ArgumentException("This request response pair is invalid."); } if (ValidResponseFormats.ContainsKey(requestName)) { List<PacketFormat> formats = ValidResponseFormats[requestName]; foreach (PacketFormat format in formats) { if (response.FirstWord == format.Name && response.WordCount - 1 >= format.MinimumParameterCount) { Dictionary<string, string> parameters = new Dictionary<string, string>(); for (int i = 1; i < response.WordCount; i++) { parameters[format.Parameters[i - 1].Name] = new string(response.Words[i].Content); } parameters["packet.Namae"] = response.FirstWord; return parameters; } } } throw new ArgumentException("Unknown request packet."); }