}//ProcessForeignServiceConnect() // // ************************************************* // **** ForeignServerConnect() **** // ************************************************* /// <summary> /// Called when a ForeignServer is connected (or re-connected) to its remote /// via a new Conversation. /// </summary> /// <param name="fs"></param> /// <param name="newConversationId"></param> protected void ForeignServerConnect(ForeignServer fs, int newConversationId = -1) { if (newConversationId >= 0) { fs.ConversationId = newConversationId; // otherwise assume caller already set id. } if (m_ServersDisconnected.Contains(fs)) // remove from disconnected list. { m_ServersDisconnected.Remove(fs); } if (m_ServersConnected.ContainsKey(fs.ConversationId)) // add to connected list { if (m_ServersConnected[fs.ConversationId] != fs) { Log.NewEntry(LogLevel.Error, "ConnectForeignServer: Error! Collision between servers {1} {0}", fs, m_ServersConnected[fs.ConversationId]); Log.NewEntry(LogLevel.Error, "ConnectForeignServer: Overwriting with new server."); m_ServersConnected[fs.ConversationId] = fs; } } else { m_ServersConnected.Add(fs.ConversationId, fs); // this is the normal situation } fs.m_Manager = this; // make sure it knows its manager. Log.NewEntry(LogLevel.Major, "ConnectForeignServer: Connected {0}", fs); }//ForeignServerConnect()
}//ForeignServerConnect() // // // **************************************************** // **** ForeignServerDisconnect() **** // **************************************************** /// <summary> /// When a conversation ends, the associated ForeignServer is moved /// to the disconnected list. Its conversation ID is set to -1. /// </summary> /// <param name="fs"></param> protected void ForeignServerDisconnect(ForeignServer fs) { int id = fs.ConversationId; if (m_ServersConnected.ContainsKey(id)) { m_ServersConnected.Remove(id); } fs.ConversationId = -1; if (!m_ServersDisconnected.Contains(fs)) { m_ServersDisconnected.Add(fs); } Log.NewEntry(LogLevel.Major, "DisconnectForeignServer: Disconnected {0}", fs); }//ForeignServerDisconnect()
}//ProcessSocketEvent // // // ************************************************************* // **** ProcessRequestMessage() **** // ************************************************************* /// <summary> /// These are Messages that originated from foreign servers. /// </summary> /// <param name="eventArg"></param> /// <param name="msg"></param> private void ProcessMessageRequests(SocketEventArgs eventArg, Message msg) { switch (msg.MessageType) { case MessageType.Credentials: // A foreign server that just connected is required to send // credentials before we tell him about our services. bool isCredentialed = true; // TODO: Test credentials if (isCredentialed) { // Connection credentials succeeded. Accept foreign connection. ForeignServer server = (ForeignServer)msg.Data[0]; ForeignServerConnect(server, eventArg.ConversationId); // Send him my services. List <IService> iServiceList = m_AppServices.GetServices(); SendServices(server.ConversationId, MessageType.ServiceAdded, iServiceList); // send server our services } else { SendMessage(eventArg.ConversationId, GetMessage(MessageType.Credentials, MessageState.Failed)); } break; case MessageType.CreateServices: break; case MessageType.ServiceAdded: break; case MessageType.ServiceRemoved: foreach (IStringifiable istring in msg.Data) { } break; case MessageType.EngineEvent: break; } //switch } // ProcessRequestMessage()
} // ProcessRequestMessage() // // // // // ************************************************************* // **** ProcessConfirmMessage() **** // ************************************************************* private void ProcessMessageResponses(SocketEventArgs eventArg, Message msg) { // Get server responding ForeignServer foreignServer = null; if (!m_ServersConnected.TryGetValue(eventArg.ConversationId, out foreignServer)) { Log.NewEntry(LogLevel.Warning, "ProcessConfirmMessage: Unknown server {0} with message: {1}", eventArg, msg); return; } switch (msg.MessageType) { case MessageType.Credentials: if (msg.State == MessageState.Confirmed) { // Our credentials were accepted. Log.NewEntry(LogLevel.Minor, "ProcessConfirmMessage: Credentials accepted by {0}", foreignServer); } else { Log.NewEntry(LogLevel.Minor, "ProcessConfirmMessage: Credentials rejected by {0}. Disconnecting.", foreignServer); m_Socket.StopConversation(foreignServer.ConversationId); ForeignServerDisconnect(foreignServer); } break; case MessageType.CreateServices: break; case MessageType.ServiceAdded: // ForeignServer has added a new service. // Here, I want to make a ghost-service that represents each service provided by the foreign server. Log.BeginEntry(LogLevel.Minor, "ProcessConfirmMessage: Services discovered on {0}:", foreignServer); foreach (IStringifiable iStr in msg.Data) { if (iStr is ForeignService) { ForeignService foreignService = (ForeignService)iStr; if (foreignServer.TryAddService(foreignService)) { Log.AppendEntry(" {0}", foreignService); } else { Log.AppendEntry(" {0}[Failed to add]", foreignService); } } } Log.EndEntry(); break; case MessageType.ServiceRemoved: foreach (IStringifiable istring in msg.Data) { } break; case MessageType.EngineEvent: // Engine events from foreign IEngineHubs. foreach (IStringifiable iString in msg.Data) { if (iString is EngineEventArgs) { EngineEventArgs e = (EngineEventArgs)iString; if (e.Status == EngineEventArgs.EventStatus.Request) { // Send this to a single hub IService iService = null; if (m_AppServices.TryGetService(e.EngineHubName, out iService) && iService is IEngineHub) { ((IEngineHub)iService).HubEventEnqueue(e); } } else { // Broadcast to all subscribed to this hub. ForeignService fs; if (foreignServer.TryGetService(e.EngineHubName, out fs) && (fs is IEngineHub)) { e.EngineHubName = fs.ServiceName; ((IEngineHub)fs).OnEngineChanged(e); } } } } break; } //switch } //ProcessConfirmMessage()
}//UpdatePeriodic() // // #endregion// Hub Event Processing #region Foreign Servers Connection & Disconnection // ********************************************************* // **** Process Request Server Connect **** // ********************************************************* /// <summary> /// This processes the local request to connect to a foreign server via a socket. /// Requirements: /// Request.Data = {ForeignConnection, /// </summary> /// <param name="requestEventArg"></param> private void ProcessRequestServerConnect(RequestEventArg <RequestCode> requestEventArg) { // Validate request if (requestEventArg.Data == null || requestEventArg.Data.Count < 1) { Log.NewEntry(LogLevel.Warning, "ProcessServerConnect: Missing data."); return; } if ((requestEventArg.Data[0] is ForeignConnection) == false) { Log.NewEntry(LogLevel.Warning, "ProcessServerConnect: Incorrect data."); return; } // Extract the ip address & create a new foreign server object for this connection. ForeignConnection conn = (ForeignConnection)requestEventArg.Data[0]; System.Net.IPAddress ipAddress; if (string.IsNullOrEmpty(conn.IpAddress) || IPAddress.TryParse(conn.IpAddress, out ipAddress) == false) { ipAddress = System.Net.IPAddress.Loopback; // Connect locally if no address provided } int portid; if (!int.TryParse(conn.Port, out portid)) { Log.NewEntry(LogLevel.Warning, "ProcessServerConnect: Failed to extract port for connection. Failed to connection {0}.", conn); return; } // On first connection attempt, we make a foreign server. if (conn.Server == null) { conn.Server = new ForeignServer(this); string baseTag = string.Empty; if (m_AppServices.User != null) { baseTag = m_AppServices.User.ToString(); } conn.Server.UniqueTag = ForeignServer.CreateUniqueTag(baseTag, DateTime.Now); // Upon first connection, we must create a unique tag. } // Connect foreign server int conversationID; if (m_Socket.TryConnect(ipAddress, portid, out conversationID)) { ForeignServerConnect(conn.Server, conversationID); // Send credentials. SendMessage(conn.Server.ConversationId, GetMessage(MessageType.Credentials, MessageState.Request, conn.Server)); // Optionally load & send config files to foreign server. if (string.IsNullOrEmpty(conn.m_ConfigFilename) == false) { string fn = string.Format("{0}{1}", m_AppServices.Info.UserConfigPath, conn.m_ConfigFilename); string stringifiedObjects = null; if (File.Exists(fn)) { try { using (StreamReader sr = new StreamReader(fn)) { stringifiedObjects = sr.ReadToEnd(); } } catch (Exception e) { Log.NewEntry(LogLevel.Warning, "Config file {0} failed to load. Exception {1}", fn, e.Message); } List <IStringifiable> nodes = null; if (Stringifiable.TryCreate(stringifiedObjects, out nodes, true)) { SendMessage(conn.Server.ConversationId, GetMessage(MessageType.CreateServices, MessageState.Request, nodes)); } } else { Log.NewEntry(LogLevel.Warning, "Config file cannot be found: {0}", fn); } } } else { // Failed to connect. Log.NewEntry(LogLevel.Warning, "ProcessForeignServiceConnect: Failed to connect to {0}", conn.Server); if (!m_ServersDisconnected.Contains(conn.Server)) { m_ServersDisconnected.Add(conn.Server); } } // Exit m_Requests.Recycle(requestEventArg);; }//ProcessForeignServiceConnect()