public void SendProvisionalResponse(CallInformation answerTo, ProvisionalResponse response) { PyPacket result = new PyPacket(PyPacket.PacketType.CALL_RSP); // ensure destination has clientID in it PyAddressClient source = answerTo.From as PyAddressClient; source.ClientID = answerTo.Client.AccountID; // switch source and dest result.Source = answerTo.To; result.Destination = source; result.UserID = source.ClientID; result.Payload = new PyTuple(0); result.OutOfBounds = new PyDictionary { ["provisional"] = new PyTuple(3) { [0] = response.Timeout, // macho timeout in seconds [1] = response.EventID, [2] = response.Arguments } }; this.Socket.Send(result); }
private void HandlePingReq(PyPacket packet, Client client) { // alter package to include the times the data PyTuple handleMessage = new PyTuple(3); PyAddressClient source = packet.Source as PyAddressClient; // this time should come from the stream packetizer or the socket itself // but there's no way we're adding time tracking for all the goddamned packets // so this should be sufficient handleMessage[0] = DateTime.UtcNow.ToFileTime(); handleMessage[1] = DateTime.UtcNow.ToFileTime(); handleMessage[2] = "server::handle_message"; PyTuple turnaround = new PyTuple(3); turnaround[0] = DateTime.UtcNow.ToFileTime(); turnaround[1] = DateTime.UtcNow.ToFileTime(); turnaround[2] = "server::turnaround"; (packet.Payload[0] as PyList)?.Add(handleMessage); (packet.Payload[0] as PyList)?.Add(turnaround); // change to a response packet.Type = PyPacket.PacketType.PING_RSP; // switch source and destination packet.Source = packet.Destination; packet.Destination = source; // queue the packet back this.Socket.Send(packet); }
public void SendException(CallInformation answerTo, PyDataType content) { // build a new packet with the correct information PyPacket result = new PyPacket(PyPacket.PacketType.ERRORRESPONSE); // ensure destination has clientID in it PyAddressClient source = answerTo.From as PyAddressClient; source.ClientID = answerTo.Client.AccountID; // switch source and dest result.Source = answerTo.To; result.Destination = source; result.UserID = source.ClientID; result.Payload = new PyTuple(3) { [0] = (int)answerTo.PacketType, [1] = (int)MachoErrorType.WrappedException, [2] = new PyTuple(1) { [0] = new PySubStream(content) }, }; this.ClusterConnection.Send(result); }
public void SendCallResult(CallInformation answerTo, PyDataType content) { PyPacket result = new PyPacket(PyPacket.PacketType.CALL_RSP); // ensure destination has clientID in it PyAddressClient source = answerTo.From as PyAddressClient; source.ClientID = answerTo.Client.AccountID; // switch source and dest result.Source = answerTo.To; result.Destination = source; result.UserID = source.ClientID; result.Payload = new PyTuple(new PyDataType[] { new PySubStream(content) }); this.Socket.Send(result); }
public void SendCallResult(CallInformation answerTo, PyDataType content) { // ensure destination has clientID in it PyAddressClient originalSource = answerTo.From as PyAddressClient; originalSource.ClientID = answerTo.Client.AccountID; this.ClusterConnection.Send( new PyPacket(PyPacket.PacketType.CALL_RSP) { // switch source and dest Source = answerTo.To, Destination = originalSource, UserID = originalSource.ClientID, Payload = new PyTuple(1) { [0] = new PySubStream(content) } } ); }
private void HandleCallReq(PyPacket packet, Client client) { PyTuple callInfo = ((packet.Payload[0] as PyTuple)[1] as PySubStream).Stream as PyTuple; string call = callInfo[1] as PyString; PyTuple args = callInfo[2] as PyTuple; PyDictionary sub = callInfo[3] as PyDictionary; PyDataType callResult = null; PyAddressClient source = packet.Source as PyAddressClient; string destinationService = null; CallInformation callInformation; if (packet.Destination is PyAddressAny destAny) { destinationService = destAny.Service; } else if (packet.Destination is PyAddressNode destNode) { destinationService = destNode.Service; if (destNode.NodeID != Container.NodeID) { Log.Fatal( "Received a call request for a node that is not us, did the ClusterController get confused or something?!" ); return; } } callInformation = new CallInformation { Client = client, CallID = source.CallID, NamedPayload = sub, PacketType = packet.Type, Service = destinationService, From = packet.Source, To = packet.Destination }; try { if (destinationService == null) { if (callInfo[0] is PyString == false) { Log.Fatal("Expected bound call with bound string, but got something different"); return; } string boundString = callInfo[0] as PyString; // parse the bound string to get back proper node and bound ids Match regexMatch = Regex.Match(boundString, "N=([0-9]+):([0-9]+)"); if (regexMatch.Groups.Count != 3) { Log.Fatal($"Cannot find nodeID and boundID in the boundString {boundString}"); return; } int nodeID = int.Parse(regexMatch.Groups[1].Value); int boundID = int.Parse(regexMatch.Groups[2].Value); if (nodeID != this.Container.NodeID) { Log.Fatal("Got bound service call for a different node"); // TODO: MIGHT BE A GOOD IDEA TO RELAY THIS CALL TO THE CORRECT NODE // TODO: INSIDE THE NETWORK, AT LEAST THAT'S WHAT CCP IS DOING BASED // TODO: ON THE CLIENT'S CODE... NEEDS MORE INVESTIGATION return; } #if DEBUG CallLog.Trace("Payload"); CallLog.Trace(PrettyPrinter.FromDataType(args)); CallLog.Trace("Named payload"); CallLog.Trace(PrettyPrinter.FromDataType(sub)); #endif callResult = this.BoundServiceManager.ServiceCall( boundID, call, args, callInformation ); #if DEBUG ResultLog.Trace("Result"); ResultLog.Trace(PrettyPrinter.FromDataType(callResult)); #endif } else { Log.Trace($"Calling {destinationService}::{call}"); #if DEBUG CallLog.Trace("Payload"); CallLog.Trace(PrettyPrinter.FromDataType(args)); CallLog.Trace("Named payload"); CallLog.Trace(PrettyPrinter.FromDataType(sub)); #endif callResult = this.ServiceManager.ServiceCall( destinationService, call, args, callInformation ); #if DEBUG ResultLog.Trace("Result"); ResultLog.Trace(PrettyPrinter.FromDataType(callResult)); #endif } this.SendCallResult(callInformation, callResult); } catch (PyException e) { this.SendException(callInformation, e); } catch (ProvisionalResponse provisional) { this.SendProvisionalResponse(callInformation, provisional); } }
private void ReceiveNormalPacketCallback(PyDataType ar) { PyPacket packet = ar; if (packet.Type == PyPacket.PacketType.CALL_REQ) { PyPacket result; PyTuple callInfo = ((packet.Payload[0] as PyTuple)[1] as PySubStream).Stream as PyTuple; string call = callInfo[1] as PyString; PyTuple args = callInfo[2] as PyTuple; PyDictionary sub = callInfo[3] as PyDictionary; PyDataType callResult = null; PyAddressClient source = packet.Source as PyAddressClient; try { if (packet.Destination is PyAddressAny destAny) { Log.Trace($"Calling {destAny.Service.Value}::{call}"); callResult = this.Container.ServiceManager.ServiceCall( destAny.Service, call, args, sub, this.Container.ClientManager.Get(packet.UserID) ); } else if (packet.Destination is PyAddressNode destNode) { Log.Trace($"Calling {destNode.Service.Value}::{call}"); callResult = this.Container.ServiceManager.ServiceCall( destNode.Service, call, args, sub, this.Container.ClientManager.Get(packet.UserID) ); } else { Log.Error($"Received packet that wasn't directed to us"); } result = new PyPacket(PyPacket.PacketType.CALL_RSP); // ensure destination has clientID in it source.ClientID = (int)packet.UserID; // switch source and dest result.Source = packet.Destination; result.Destination = source; result.UserID = packet.UserID; result.Payload = new PyTuple(new PyDataType[] { new PySubStream(callResult) }); } catch (PyException e) { // PyExceptions have to be relayed to the client // this way it's easy to notify the user without needing any special code result = new PyPacket(PyPacket.PacketType.ERRORRESPONSE); source.ClientID = (int)packet.UserID; result.Source = packet.Destination; result.Destination = source; result.UserID = packet.UserID; result.Payload = new PyTuple(new PyDataType[] { (int)packet.Type, (int)MachoErrorType.WrappedException, new PyTuple(new PyDataType[] { new PySubStream(e) }), }); } // any of the paths that lead to the send here must have the PyPacket initialized // so a null check is not needed this.Socket.Send(result); } else if (packet.Type == PyPacket.PacketType.SESSIONCHANGENOTIFICATION) { Log.Debug($"Updating session for client {packet.UserID}"); // ensure the client is registered in the node and store his session if (this.Container.ClientManager.Contains(packet.UserID) == false) { this.Container.ClientManager.Add(packet.UserID, new Client()); } this.Container.ClientManager.Get(packet.UserID).UpdateSession(packet); } }