private void ReceiveNodeInitialState(PyDataType ar) { if (ar is PyObjectData == false) { throw new Exception($"Expected PyObjectData for machoNet.nodeInfo but got {ar.GetType()}"); } PyObjectData info = ar as PyObjectData; if (info.Name != "machoNet.nodeInfo") { throw new Exception($"Expected PyObjectData of type machoNet.nodeInfo but got {info.Name}"); } // Update our local info NodeInfo nodeinfo = info; this.Container.NodeID = nodeinfo.nodeID; Log.Debug("Found machoNet.nodeInfo, our new node id is " + nodeinfo.nodeID.ToString("X4")); // load the specified solar systems this.SystemManager.LoadSolarSystems(nodeinfo.solarSystems); // finally set the new packet handler this.Socket.SetReceiveCallback(ReceiveNormalPacketCallback); }
/// <summary> /// Converts a KeyVal to a normal PyDictionary /// </summary> /// <param name="from">The KeyVal to convert to a dictionary</param> /// <returns>The information in the keyval</returns> /// <exception cref="InvalidCastException">If the type is not a keyval</exception> public static PyDictionary ToDictionary(PyObjectData from) { if (from.Name != OBJECT_NAME) { throw new InvalidCastException($"Trying to cast a {from.Name} to a {OBJECT_NAME}"); } return(from.Arguments as PyDictionary); }
private void ProcessObjectData(PyObjectData data) { this.mStringBuilder.AppendFormat("[PyObjectData {0}]", data.Name.Value); this.mStringBuilder.AppendLine(); this.mIndentation++; this.Process(data.Arguments); this.mIndentation--; }
private PyObject HandleObject(PyObjectData dat) { // Only exceptions should be this type PyException ex = new PyException(); if (ex.Decode(dat) == false) { Log.Error("Connection", "Unhandled PyObjectData packet"); return(null); } Log.Error("Connection", "Got an exception packet of type: " + ex.exception_type + ". " + ex.message); throw new DisconnectException(); }
public PyDataType DeleteContract(PyInteger contractID, PyObjectData keyVal, CallInformation call) { using MySqlConnection connection = this.MarketDB.AcquireMarketLock(); try { // get contract type and status // get the items back to where they belong (if any) // } finally { this.MarketDB.ReleaseMarketLock(connection); } return(null); }
public PyList FetchLiveUpdates() { try { MySqlConnection connection = null; MySqlDataReader reader = Database.Query(ref connection, "SELECT updateID, updateName, description, machoVersionMin, machoVersionMax, buildNumberMin, buildNumberMax, methodName, objectID, codeType, code, OCTET_LENGTH(code) as codeLength FROM eveLiveUpdates" ); using (connection) using (reader) { PyList result = new PyList(); while (reader.Read()) { PyDictionary entry = new PyDictionary(); PyDictionary code = new PyDictionary(); // read the blob for the liveupdate byte[] buffer = new byte[reader.GetUInt32(11)]; reader.GetBytes(10, 0, buffer, 0, buffer.Length); code["code"] = buffer; code["codeType"] = reader.GetString(9); code["methodName"] = reader.GetString(7); code["objectID"] = reader.GetString(8); entry["code"] = new PyObjectData("util.KeyVal", code); result.Add( new PyObjectData("util.KeyVal", entry) ); } return(result); } } catch (Exception) { Log.Error($"Cannot prepare live-updates information for client"); throw; } }
public bool Decode(PyObject data) { if (data.Type != PyObjectType.ObjectData) { Log.Error("ClientSessionData", "Wrong container type"); return(false); } PyObjectData container = data as PyObjectData; if (container.Name != "macho.sessionInitialState") { Log.Error("ClientSessionData", "Wrong container name/type"); return(false); } PyTuple args = container.Arguments as PyTuple; if (args.Items.Count != 2) { Log.Error("ClientSessionData", "Wrong args count"); return(false); } if (args.Items[0].Type != PyObjectType.Dict) { Log.Error("ClientSessionData", "Arguments first element is not PyDict"); return(false); } session = args.Items[0] as PyDict; if ((args.Items[1] is PyInt) == false) { Log.Error("ClientSessionData", "Arguments second element is not PyInt"); return(false); } clientID = (args.Items[1] as PyInt).Value; return(true); }
public bool Decode(PyObject info) { if (info.Type != PyObjectType.ObjectData) { Log.Error("NodeInfo", "Wrong type for ObjectData"); return(false); } PyObjectData data = info.As <PyObjectData>(); if (data.Name != "machoNet.nodeInfo") { Log.Error("NodeInfo", "Wrong object name, expected machoNet.nodeInfo but got " + data.Name); return(false); } if (data.Arguments.Type != PyObjectType.Tuple) { Log.Error("NodeInfo", "Wrong type for ObjectData arguments, expected Tuple"); return(false); } PyTuple args = data.Arguments.As <PyTuple>(); if (args.Items[0].Type != PyObjectType.Long) { Log.Error("NodeInfo", "Wrong type for tuple0 item0, expected int"); return(false); } nodeID = args.Items[0].As <PyInt>().Value; if (args.Items[1].Type != PyObjectType.List) { Log.Error("NodeInfo", "Wrong type for tuple0 item1, expected list"); return(false); } solarSystems = args.Items[1].As <PyList>(); return(true); }
static void Main(string[] args) { Log.Init("evesharp"); Log.Info("Main", "Starting node..."); Log.Info("Database", "Loading database.conf file"); string[] lines = File.ReadAllLines("database.conf"); Database.Database.Username = lines[0]; Database.Database.Password = lines[1]; Database.Database.Host = lines[2]; Database.Database.DB = lines[3]; Log.Trace("Database", "Connecting to database..."); if (Database.Database.Init() == false) { Log.Error("Main", "Cannot connect to database"); while (true) { ; } } /* * SHA1 sha1 = SHA1.Create(); * byte[] hash = sha1.ComputeHash(Encoding.ASCII.GetBytes("password")); * char[] strHash = new char[20]; * * for (int i = 0; i < 20; i++) * { * strHash[i] = (char)hash[i]; * } * * string str = new string(strHash); * * Database.Database.Query("INSERT INTO account(accountID, accountName, password, role, online, banned)VALUES(NULL, 'Username', '" + str + "', 2, 0, 0);"); * * Database.Database.Query("INSERT INTO account(accountID, accountName, password, role, online, banned)VALUES(NULL, 'Username', SHA1('password'), 2, 0, 0);");*/ Log.Info("Main", "Connection to the DB sucessfull"); Log.Info("Main", "Generating default cache data"); Cache.GenerateCache(); Log.Debug("Main", "Done"); Log.Info("Main", "Connecting to proxy..."); proxyConnection = new TCPSocket(ushort.Parse(proxy[0, 1]), false); if (proxyConnection.Connect(proxy[0, 0]) == false) { Log.Error("Main", "Cannot connect to proxy. Halting"); Database.Database.Stop(); while (true) { ; } } Log.Trace("Main", "Server started"); while (true) { Thread.Sleep(1); try { byte[] data = new byte[proxyConnection.Available]; int bytes = proxyConnection.Recv(data); if (bytes == -1) { // Proxy is closing, shutdown the node break; } else if (bytes > 0) { packetizer.QueuePackets(data, bytes); int p = packetizer.ProcessPackets(); for (int i = 0; i < p; i++) { byte[] packet = packetizer.PopItem(); PyObject obj = Unmarshal.Process <PyObject>(packet); if (obj is PyObjectData) { PyObjectData info = obj as PyObjectData; if (info.Name == "machoNet.nodeInfo") { // Update our local info NodeInfo nodeinfo = new NodeInfo(); if (nodeinfo.Decode(info) == true) { nodeID = nodeinfo.nodeID; Log.Debug("Main", "Found machoNet.nodeInfo, our new node id is " + nodeID.ToString("X4")); SystemManager.LoadSolarSystems(nodeinfo.solarSystems); } } else { // Client packet PyPacket clientpacket = new PyPacket(); if (clientpacket.Decode(info) == false) { Log.Error("Main", "Unknown packet"); } else { // Something similar to Async calls new Thread(new ParameterizedThreadStart(HandlePacket)).Start(clientpacket); } } } else if (obj is PyChecksumedStream) // Checksumed packets { PyPacket clientpacket = new PyPacket(); if (clientpacket.Decode(obj) == false) { Log.Error("Main", "Cannot decode packet"); } else { new Thread(new ParameterizedThreadStart(HandlePacket)).Start(clientpacket); } } else if (obj is PyTuple) { // The only tuple packet is the LowLevelVersionExchange LowLevelVersionExchange ex = new LowLevelVersionExchange(); if (ex.Decode(obj) == false) { Log.Error("Main", "LowLevelVersionExchange error"); } // Reply with the node LowLevelVersionExchange LowLevelVersionExchange reply = new LowLevelVersionExchange(); reply.codename = Common.Constants.Game.codename; reply.birthday = Common.Constants.Game.birthday; reply.build = Common.Constants.Game.build; reply.machoVersion = Common.Constants.Game.machoVersion; reply.version = Common.Constants.Game.version; reply.region = Common.Constants.Game.region; Send(reply.Encode(true)); } else if (obj is PyObjectEx) { Log.Error("PyObjectEx", PrettyPrinter.Print(obj)); } else { Log.Error("Main", PrettyPrinter.Print(obj)); Log.Error("Main", "Unhandled packet type"); } } } } catch (Exception) { } } /* Code to ADD an account: * SHA1 sha1 = SHA1.Create(); * byte[] hash = sha1.ComputeHash(Encoding.ASCII.GetBytes("password")); * char[] strHash = new char[20]; * * for (int i = 0; i < 20; i++) * { * strHash[i] = (char)hash[i]; * } * * string str = new string(strHash); * * Database.Database.Query("INSERT INTO account(accountID, accountName, password, role, online, banned)VALUES(NULL, 'Username', '" + str + "', 2, 0, 0);"); */ }
static void Main(string[] args) { Log.Init("evesharp"); Log.Info("Main", "Starting node..."); Log.Trace("Database", "Connecting to database..."); if (Database.Database.Init() == false) { Log.Error("Main", "Cannot connect to database"); while (true) { ; } } /* * DBRowDescriptor descriptor = new DBRowDescriptor(); * * descriptor.AddColumn("itemID", FieldType.I4); * descriptor.AddColumn("custominfo", FieldType.Str); * * PyPackedRow packed = new PyPackedRow(descriptor); * * packed.SetValue("itemID", new PyInt(500)); * packed.SetValue("custominfo", new PyString("hello world")); * * byte[] marshaled = Marshal.Marshal.Process(packed); * * PyPackedRow unmarshaled = Unmarshal.Process<PyPackedRow>(marshaled); * * Console.WriteLine(PrettyPrinter.Print(unmarshaled)); */ byte[] raw = new byte[] { 1, 0, 55, 1, 22, 33, 0, 33, 25, 33, 14, 0, 0, 25, 45 }; MemoryStream output = new MemoryStream(raw); BinaryReader reader = new BinaryReader(output); MemoryStream stream = new MemoryStream(); BinaryWriter streamWriter = new BinaryWriter(stream); BinaryReader streamReader = new BinaryReader(stream); PyPackedRow.ZeroCompress(reader, output, streamWriter); byte[] compressed = stream.ToArray(); stream.Seek(0, SeekOrigin.Begin); byte[] uncompress = PyPackedRow.LoadZeroCompressed(streamReader); while (true) { Thread.Sleep(1); } /* * SHA1 sha1 = SHA1.Create(); * byte[] hash = sha1.ComputeHash(Encoding.ASCII.GetBytes("password")); * char[] strHash = new char[20]; * * for (int i = 0; i < 20; i++) * { * strHash[i] = (char)hash[i]; * } * * string str = new string(strHash); * * Database.Database.Query("INSERT INTO account(accountID, accountName, password, role, online, banned)VALUES(NULL, 'Username', '" + str + "', 2, 0, 0);"); */ Log.Info("Main", "Connection to the DB sucessfull"); Log.Trace("Main", "Registering services..."); SvcMgr.AddService(new Services.Network.machoNet()); SvcMgr.AddService(new Services.Network.alert()); SvcMgr.AddService(new Services.CacheSvc.objectCaching()); Log.Info("Main", "Done"); Log.Info("Main", "Connecting to proxy..."); proxyConnection = new TCPSocket(ushort.Parse(proxy[0, 1]), false); if (proxyConnection.Connect(proxy[0, 0]) == false) { Log.Error("Main", "Cannot connect to proxy. Halting"); Database.Database.Stop(); while (true) { ; } } Log.Trace("Main", "Server started"); while (true) { Thread.Sleep(1); try { byte[] data = new byte[proxyConnection.Available]; int bytes = proxyConnection.Recv(data); if (bytes == -1) { // Proxy is closing, shutdown the node break; } else if (bytes > 0) { packetizer.QueuePackets(data, bytes); int p = packetizer.ProcessPackets(); for (int i = 0; i < p; i++) { byte[] packet = packetizer.PopItem(); PyObject obj = Unmarshal.Process <PyObject>(packet); if (obj is PyObjectData) { PyObjectData info = obj as PyObjectData; if (info.Name == "machoNet.nodeInfo") { // Update our local info NodeInfo nodeinfo = new NodeInfo(); if (nodeinfo.Decode(info) == true) { nodeID = nodeinfo.nodeID; SystemManager.LoadSolarSystems(nodeinfo.solarSystems); } } else { // Client packet PyPacket clientpacket = new PyPacket(); if (clientpacket.Decode(info) == false) { Log.Error("Main", "Unknown packet"); } else { // Something similar to Async calls new Thread(new ParameterizedThreadStart(HandlePacket)).Start(clientpacket); } } } else if (obj is PyChecksumedStream) // Checksumed packets { PyPacket clientpacket = new PyPacket(); if (clientpacket.Decode(obj) == false) { Log.Error("Main", "Cannot decode packet"); } else { new Thread(new ParameterizedThreadStart(HandlePacket)).Start(clientpacket); } } else if (obj is PyTuple) { // The only tuple packet is the LowLevelVersionExchange LowLevelVersionExchange ex = new LowLevelVersionExchange(); if (ex.Decode(obj) == false) { Log.Error("Main", "LowLevelVersionExchange error"); } // Reply with the node LowLevelVersionExchange LowLevelVersionExchange reply = new LowLevelVersionExchange(); reply.codename = Common.Constants.Game.codename; reply.birthday = Common.Constants.Game.birthday; reply.build = Common.Constants.Game.build; reply.machoVersion = Common.Constants.Game.machoVersion; reply.version = Common.Constants.Game.version; reply.region = Common.Constants.Game.region; Send(reply.Encode(true)); } else if (obj is PyObjectEx) { Log.Error("PyObjectEx", PrettyPrinter.Print(obj)); } else { Log.Error("Main", PrettyPrinter.Print(obj)); Log.Error("Main", "Unhandled packet type"); } } } } catch (Exception) { } } /* Code to ADD an account: * SHA1 sha1 = SHA1.Create(); * byte[] hash = sha1.ComputeHash(Encoding.ASCII.GetBytes("password")); * char[] strHash = new char[20]; * * for (int i = 0; i < 20; i++) * { * strHash[i] = (char)hash[i]; * } * * string str = new string(strHash); * * Database.Database.Query("INSERT INTO account(accountID, accountName, password, role, online, banned)VALUES(NULL, 'Username', '" + str + "', 2, 0, 0);"); */ }
/// <summary> /// Converts the given <paramref name="data"/> to it's byte array representation. /// ObjectData are simple representations of Python objects. /// These objects are composed by one python string that indicates the type of the object (it's name) /// and an argument object that can be any kind of Python type /// /// The following opcodes are supported /// <seealso cref="Opcode.ObjectData" /> /// </summary> /// <param name="writer">Where to write the encoded data to</param> /// <param name="data">The value to write</param> private static void ProcessObjectData(BinaryWriter writer, PyObjectData data) { writer.WriteOpcode(Opcode.ObjectData); Process(writer, data.Name); Process(writer, data.Arguments); }
public PyDataType PlaceBid(PyInteger contractID, PyInteger quantity, PyBool forCorp, PyObjectData locationData, CallInformation call) { using MySqlConnection connection = this.MarketDB.AcquireMarketLock(); try { // TODO: SUPPORT PROPER CORP WALLET int bidderID = call.Client.EnsureCharacterIsSelected(); if (forCorp == true) { bidderID = call.Client.CorporationID; throw new UserError("Corp bidding is not supported for now!"); } ContractDB.Contract contract = this.DB.GetContract(connection, contractID); // ensure the contract is still in progress if (contract.Status != ContractStatus.Outstanding) { throw new ConAuctionAlreadyClaimed(); } this.DB.GetMaximumBid(connection, contractID, out int maximumBidderID, out int maximumBid); // calculate next bid slot int nextMinimumBid = maximumBid + (int)Math.Max(0.1 * (double)contract.Price, 1000); if (quantity < nextMinimumBid) { throw new ConBidTooLow(quantity, nextMinimumBid); } // take the bid's money off the wallet using Wallet bidderWallet = this.WalletManager.AcquireWallet(bidderID, 1000); { bidderWallet.EnsureEnoughBalance(quantity); bidderWallet.CreateJournalRecord( MarketReference.ContractAuctionBid, null, null, -quantity ); } // check who we'd outbid and notify them this.DB.GetOutbids(connection, contractID, quantity, out List <int> characterIDs, out List <int> corporationIDs); OnContractOutbid notification = new OnContractOutbid(contractID); foreach (int corporationID in corporationIDs) { if (corporationID != bidderID) { this.NotificationManager.NotifyCorporation(corporationID, notification); } } foreach (int characterID in characterIDs) { if (characterID != bidderID) { this.NotificationManager.NotifyCharacter(characterID, notification); } } // finally place the bid ulong bidID = this.DB.PlaceBid(connection, contractID, quantity, bidderID, forCorp); // return the money for the player that was the highest bidder using Wallet maximumBidderWallet = this.WalletManager.AcquireWallet(maximumBidderID, 1000); { maximumBidderWallet.CreateJournalRecord( MarketReference.ContractAuctionBidRefund, null, null, maximumBid, "" ); } return(bidID); } finally { this.MarketDB.ReleaseMarketLock(connection); } }
public PyDataType GetContractList(PyObjectData filtersKeyval, CallInformation call) { PyDictionary <PyString, PyDataType> filters = KeyVal.ToDictionary(filtersKeyval).GetEnumerable <PyString, PyDataType>(); PyList <PyInteger> notIssuedByIDs = null; PyList <PyInteger> issuedByIDs = null; call.NamedPayload.TryGetValue("startContractID", out PyInteger startContractID); int resultsPerPage = call.NamedPayload["num"] as PyInteger; filters.TryGetValue("regionID", out PyInteger regionID); filters.TryGetValue("stationID", out PyInteger stationID); filters.TryGetValue("solarSystemID", out PyInteger solarSystemID); filters.TryGetValue("itemTypeID", out PyInteger itemTypeID); filters.TryGetValue("assigneeID", out PyInteger assigneeID); filters.TryGetValue("itemGroupID", out PyInteger itemGroupID); filters.TryGetValue("itemCategoryID", out PyInteger itemCategoryID); filters.TryGetValue("priceMax", out PyInteger priceMax); filters.TryGetValue("priceMin", out PyInteger priceMin); filters.TryGetValue("type", out PyInteger type); filters.TryGetValue("description", out PyString description); if (priceMax < 0 || priceMin < 0 || priceMax < priceMin) { throw new ConMinMaxPriceError(); } if (filters.TryGetValue("issuedByIDs", out PyList issuedIDs) == true && issuedIDs is not null) { issuedByIDs = issuedIDs.GetEnumerable <PyInteger>(); } if (filters.TryGetValue("notIssuedByIDs", out PyList notIssuedIDs) == true && notIssuedIDs is not null) { notIssuedByIDs = notIssuedIDs.GetEnumerable <PyInteger>(); } // limit the number of results to 100 if (resultsPerPage > 100) { resultsPerPage = 100; } int?locationID = null; if (stationID is not null) { locationID = stationID; } else if (solarSystemID is not null) { locationID = solarSystemID; } else if (regionID is not null) { locationID = regionID; } List <int> contractList = this.DB.GetContractList( startContractID, resultsPerPage, itemTypeID, notIssuedByIDs, issuedByIDs, assigneeID, locationID, itemGroupID, itemCategoryID, priceMax ?? 0, priceMin ?? 0, type, description, call.Client.EnsureCharacterIsSelected(), call.Client.CorporationID ); return(KeyVal.FromDictionary(new PyDictionary() { ["contracts"] = this.DB.GetInformationForContractList(contractList), ["bids"] = this.DB.GetBidsForContractList(contractList), ["items"] = this.DB.GetItemsForContractList(contractList) } )); }
public void ReceiveNodeAsync(IAsyncResult ar) { try { AsyncState state = (AsyncState)(ar.AsyncState); int bytes = Socket.Socket.EndReceive(ar); packetizer.QueuePackets(state.buffer, bytes); int p = packetizer.ProcessPackets(); for (int i = 0; i < p; i++) { byte[] packet = packetizer.PopItem(); PyObject obj = Unmarshal.Process <PyObject>(packet); if (obj == null) { Log.Debug("Node", "Null packet received"); continue; } if ((obj is PyObjectData) == false) { Log.Debug("Node", "Non-valid node packet. Dropping"); continue; } PyObjectData item = obj as PyObjectData; if (item.Name == "macho.CallRsp") { PyPacket final = new PyPacket(); if (final.Decode(item) == false) { Log.Error("Node", "Cannot decode packet"); continue; } if (final.dest.type == PyAddress.AddrType.Client) { ConnectionManager.NotifyClient((int)(final.userID), obj); } else if (final.dest.type == PyAddress.AddrType.Node) { ConnectionManager.NotifyNode((int)(final.dest.typeID), obj); } else if (final.dest.type == PyAddress.AddrType.Broadcast) { Log.Error("Node", "Broadcast packets not supported yet"); } // TODO: Handle Broadcast packets } else { Log.Error("Node", string.Format("Wrong packet name: {0}", item.Name)); } } Socket.Socket.BeginReceive(state.buffer, 0, 8192, SocketFlags.None, recvAsync, state); } catch (ObjectDisposedException) { Log.Debug("Node", "Disconnected"); ConnectionManager.RemoveConnection(this); } catch (SocketException) { Log.Debug("Node", "Disconnected"); ConnectionManager.RemoveConnection(this); } catch (Exception ex) { Log.Error("Node", "Caught unhandled exception: " + ex.ToString()); } }
public void Run() { while (true) { Thread.Sleep(1); try { byte[] data = new byte[socket.Available]; int bytes = socket.Recv(data); if (bytes == -1) { throw new DisconnectException(); } else if (bytes > 0) { packetizer.QueuePackets(data, bytes); int p = packetizer.ProcessPackets(); for (int i = 0; i < p; i++) { byte[] packet = packetizer.PopItem(); PyObject obj = Unmarshal.Process <PyObject>(packet); if (obj.Type == PyObjectType.ObjectData) { Log.Warning("Node", PrettyPrinter.Print(obj)); PyObjectData item = obj as PyObjectData; if (item.Name == "macho.CallRsp") { PyPacket final = new PyPacket(); if (final.Decode(item) == true) { if (final.dest.type == PyAddress.AddrType.Client) { try { ClientManager.NotifyClient((int)final.userID, obj); } catch (Exception) { Log.Error("Node", "Trying to send a packet to a non-existing client"); } } else if (final.dest.type == PyAddress.AddrType.Node) { NodeManager.NotifyNode((int)final.dest.typeID, obj); } else if (final.dest.type == PyAddress.AddrType.Broadcast) { // This should not be coded like this here, but will do the trick for now // TODO: Add a ClientManager ClientManager.NotifyClients(obj); } } } } else { Log.Error("Node", "Unknown type"); } } } } catch (SocketException ex) { if (ex.ErrorCode != 10035) { break; } } catch (DisconnectException) { Log.Error("Node", "Node " + NodeManager.GetNodeID(this) + " disconnected"); break; } catch (Exception) { } } }