/// <summary> /// Diese Methode dient zur Anbindung der P2P Topology an die Hierarchische. /// Es wird ein entsprechendes Paket in das hierarchische Netz gesendet. /// </summary> /// <param name="p2pRequest"></param> /// <param name="username"></param> /// <param name="kaEvent"></param> /// <param name="writeResult">übergebe die Methode writeResult</param> void ConnectP2P(P2PRequest p2pRequest, string username, KaEvent kaEvent, Action <Request, string> writeResult) { //P2P Teil P2PPackage p2p = new P2PPackage(username, kaEvent) { P2Prequest = p2pRequest }; //Sende Teil Package sendPackage = new Package(p2p); Package recievePackage; recievePackage = Send(sendPackage, KnownServers.GetRandomWellKnownPeer()); if (recievePackage != null) { switch (recievePackage.p2p.P2PAnswer) { case P2PAnswer.Success: writeResult(Request.Success, InviteSuccess); break; case P2PAnswer.Failure: writeResult(Request.Failure, InviteFail); break; default: writeResult(Request.Failure, InviteFail); break; } } else { writeResult(Request.Error, Error); } }
/// <summary> /// Resolve Acquired Packages and trigger corresponding requests. For Client /// </summary> /// <param name="package"></param> public Package ResolvePackage(Package package) { switch (package.request) { /// In case of Login Request try to login to the server database and set Request accordingly case Request.Login: Console.WriteLine(LoginRequest); if (package.serverSwitched) { if (database.Login(package.user)) { List <KaEvent> kaEvents; kaEvents = database.Read(package.user.name); package.kaEvents = kaEvents; try { package.invites = database.ReadInvites(package.user.name); } catch (Exception ex) { Console.WriteLine("ReadInvites failed.\n{0}\n{1}", ex.Message, ex.StackTrace); } writeResult(Request.Success, LoginSuccess); } else { writeResult(Request.Failure, LoginFail); } } else { if (ServerConfig.structure == Structure.HIERARCHY) { ///if serverID > 0 => Hierarchy if (package.user.serverID > 0) { //Hierarchie Login HierarchiePackage hierarchie = new HierarchiePackage { HierarchieRequest = HierarchieRequest.UserLogin, login = package.user.name, destinationID = package.user.serverID }; hierarchie = HierarchyLogic.ResolveHierarchie(hierarchie); switch (hierarchie.HierarchieAnswer) { case HierarchieAnswer.Success: package.sourceServer = hierarchie.destinationAdress; writeResult(Request.ChangeServer, ChangeServer); break; case HierarchieAnswer.Failure: writeResult(Request.Failure, LoginFail); break; case HierarchieAnswer.Error: writeResult(Request.Error, Error); break; default: writeResult(Request.Failure, Error); break; } } ///else => Send to P2P else { //P2P Teil P2PPackage p2p = new P2PPackage(package.user.name) { P2Prequest = P2PRequest.Login }; //Sende Teil Package sendPackage = new Package(p2p); Package recievePackage; recievePackage = Send(sendPackage, KnownServers.GetRandomWellKnownPeer()); if (recievePackage != null) { switch (recievePackage.p2p.P2PAnswer) { case P2PAnswer.Success: package.sourceServer = recievePackage.p2p.lastIP; writeResult(Request.ChangeServer, ChangeServer); break; case P2PAnswer.Failure: writeResult(Request.Failure, LoginFail); break; default: writeResult(Request.Failure, LoginFail); break; } } else { writeResult(Request.Error, Error); } } } else if (ServerConfig.structure == Structure.P2P) { ///if serverID == 0 => P2P if (package.user.serverID == 0) { //P2P Teil P2PPackage p2p = new P2PPackage(package.user.name) { P2Prequest = P2PRequest.Login }; p2p = P2PLogic.ResolveP2P(p2p); switch (p2p.P2PAnswer) { case P2PAnswer.Success: package.sourceServer = p2p.lastIP; writeResult(Request.ChangeServer, ChangeServer); break; case P2PAnswer.Failure: writeResult(Request.Failure, LoginFail); break; default: writeResult(Request.Failure, LoginFail); break; } } ///else => Send to Hierarchy else { //Hierarchie Login HierarchiePackage hierarchie = new HierarchiePackage { HierarchieRequest = HierarchieRequest.UserLogin, login = package.user.name, destinationID = package.user.serverID }; //Sende Teil Package sendPackage = new Package(hierarchie); Package recievePackage; recievePackage = Send(sendPackage, KnownServers.Root); if (recievePackage != null) { switch (hierarchie.HierarchieAnswer) { case HierarchieAnswer.Success: package.sourceServer = hierarchie.destinationAdress; writeResult(Request.ChangeServer, ChangeServer); break; case HierarchieAnswer.Failure: writeResult(Request.Failure, LoginFail); break; case HierarchieAnswer.Error: writeResult(Request.Error, Error); break; default: writeResult(Request.Failure, Error); break; } } else { writeResult(Request.Error, Error); } } } } break; /// In case of Register Request try to login to the server database and set Request accordingly case Request.Register: Console.WriteLine(RegisterRequest); try { if (package.serverSwitched) { if (database.RegisterUser(package.user, package.passwordConfirm)) { writeResult(Request.Success, RegisterSuccess); package.user.serverID = ServerConfig.serverID; } else { writeResult(Request.Failure, RegisterFail); } } else { if (ServerConfig.structure == Structure.HIERARCHY) { //Hierarchie Teil HierarchiePackage hierarchie = new HierarchiePackage { HierarchieRequest = HierarchieRequest.RegisterUser }; hierarchie = HierarchyLogic.ResolveHierarchie(hierarchie); if (hierarchie.HierarchieAnswer == HierarchieAnswer.UserExistent) { writeResult(Request.UserExistent, UserExistent); break; } //P2P Teil //ConnectP2P(P2PRequest.NewUser, package.user.name, writeResult); //P2P Teil P2PPackage p2p = new P2PPackage(package.user.name) { P2Prequest = P2PRequest.NewUser }; //Sende Teil Package sendPackage = new Package(p2p); Package recievePackage; recievePackage = Send(sendPackage, KnownServers.GetRandomWellKnownPeer()); if (recievePackage != null) { switch (recievePackage.p2p.P2PAnswer) { case P2PAnswer.Success: if (hierarchie.anzUser < recievePackage.p2p.anzUser) { package.sourceServer = hierarchie.destinationAdress; } else { package.sourceServer = recievePackage.p2p.lastIP; } writeResult(Request.ChangeServer, ChangeServer); break; ///user already exists case P2PAnswer.UserExistent: writeResult(Request.UserExistent, UserExistent); break; case P2PAnswer.Error: Console.WriteLine(recievePackage.p2p.ErrorMsg); writeResult(Request.Error, Error); break; default: package.sourceServer = hierarchie.destinationAdress; writeResult(Request.ChangeServer, ChangeServer); break; } } else { package.sourceServer = hierarchie.destinationAdress; writeResult(Request.ChangeServer, ChangeServer); } } else if (ServerConfig.structure == Structure.P2P) { //P2P Teil P2PPackage p2p = new P2PPackage { P2Prequest = P2PRequest.NewUser }; p2p = P2PLogic.ResolveP2P(p2p); ///user is already existent if (p2p.P2PAnswer == P2PAnswer.Visited) { writeResult(Request.UserExistent, UserExistent); break; } //Hierarchie Teil HierarchiePackage hierarchie = new HierarchiePackage { HierarchieRequest = HierarchieRequest.RegisterUser }; //Sende Teil Package sendPackage = new Package(hierarchie); Package recievePackage; recievePackage = Send(sendPackage, KnownServers.Root); if (recievePackage != null) { switch (recievePackage.hierarchie.HierarchieAnswer) { case HierarchieAnswer.Success: if (p2p.anzUser < recievePackage.hierarchie.anzUser) { package.sourceServer = p2p.lastIP; } else { package.sourceServer = recievePackage.hierarchie.destinationAdress; } writeResult(Request.ChangeServer, RegisterSuccess); break; ///user already exists case HierarchieAnswer.UserExistent: writeResult(Request.UserExistent, UserExistent); break; default: package.sourceServer = p2p.lastIP; writeResult(Request.ChangeServer, ChangeServer); break; } } else { package.sourceServer = p2p.lastIP; writeResult(Request.ChangeServer, ChangeServer); } } } } catch (Exception e) { Console.WriteLine(e.GetType().FullName); Console.WriteLine(e.Message); writeResult(Request.Failure, RegisterFail); } break; case Request.Save: Console.WriteLine(SaveRequest); try { database.SaveEvent(package.kaEvents[0]); writeResult(Request.Success, SaveSuccess); } catch (Exception e) { Console.WriteLine(e.GetType().FullName); Console.WriteLine(e.Message); writeResult(Request.Failure, SaveFail); } break; case Request.Delete: Console.WriteLine(DeleteRequest); try { database.DeleteEvent(package.kaEvents[0].TerminID); writeResult(Request.Success, DeleteSuccess); } catch (Exception e) { Console.WriteLine(e.GetType().FullName); Console.WriteLine(e.Message); writeResult(Request.Failure, DeleteFail); } break; case Request.Load: Console.WriteLine(LoadRequest); try { List <KaEvent> kaEvents; //kaEvents = database.LoadEvents(package.user, package.kaEvents[0].Beginn); kaEvents = database.Read(package.user.name); package.kaEvents = kaEvents; writeResult(Request.Success, LoadSuccess); } catch (Exception e) { Console.WriteLine(e.GetType().FullName); Console.WriteLine(e.Message); writeResult(Request.Failure, LoadFail); } break; case Request.Test: Console.WriteLine(TestRequest); break; case Request.Invite: //Prüfung ServerID Console.WriteLine(InviteRequest); if (ServerConfig.structure == Structure.HIERARCHY) { /* * Hier ist nur Client-Server. * Wenn Server-Server Invite message ist, wird es bei resolveHierarchie erledigt * Das hier sollte wenn möglich als Asynchron, bzw. nach art Fire und Forget. * Wenn mehrere User eingetragen wird, hat der Server eine lange Anschreibezeit * */ foreach (User member in package.kaEvents[0].members) { ///member is user in current server if (member.serverID == ServerConfig.serverID) { if (database.UserExist(member.name)) { database.SaveInvites(member.name, package.kaEvents[0]); writeResult(Request.Success, InviteSuccess); } else { writeResult(Request.Failure, UserNotFound); } } ///member is user in hierarchy topology else if (member.serverID > 0) { HierarchiePackage hierarchie = new HierarchiePackage { HierarchieRequest = HierarchieRequest.Invite, invite = package.kaEvents[0], login = member.name, destinationID = member.serverID }; HierarchyLogic.ResolveHierarchie(hierarchie); switch (hierarchie.HierarchieAnswer) { case HierarchieAnswer.Success: writeResult(Request.Success, InviteSuccess); break; case HierarchieAnswer.Failure: writeResult(Request.Failure, InviteFail); break; default: break; } } ///member is user in p2p topology else { //P2P Teil P2PPackage p2p = new P2PPackage(member.name, package.kaEvents[0]) { P2Prequest = P2PRequest.Invite }; //Sende Teil Package sendPackage = new Package(p2p); Package recievePackage; recievePackage = Send(sendPackage, KnownServers.GetRandomWellKnownPeer()); if (recievePackage != null) { switch (recievePackage.p2p.P2PAnswer) { case P2PAnswer.Success: writeResult(Request.Success, InviteSuccess); break; case P2PAnswer.Failure: writeResult(Request.Failure, InviteFail); break; default: writeResult(Request.Failure, InviteFail); break; } } else { writeResult(Request.Error, Error); } } } } else if (ServerConfig.structure == Structure.P2P) { //Logik P2P Invite List <User> list = package.kaEvents[0].members; foreach (User member in list) { ///member is user in p2p topology if (member.serverID == 0) { if (database.UserExist(member.name)) { database.SaveInvites(member.name, package.kaEvents[0]); writeResult(Request.Success, InviteSuccess); } else { P2PPackage p2p = new P2PPackage(member.name, package.kaEvents[0]) { P2Prequest = P2PRequest.Invite }; p2p = P2PLogic.ResolveP2P(p2p); switch (p2p.P2PAnswer) { case P2PAnswer.Success: writeResult(Request.Success, InviteSuccess); break; case P2PAnswer.Failure: writeResult(Request.Failure, InviteFail); break; default: writeResult(Request.Error, Error); break; } } } ///member is user in hierarchy topology else { //Hierarchie Teil HierarchiePackage hierarchie = new HierarchiePackage { HierarchieRequest = HierarchieRequest.Invite, invite = package.kaEvents[0], login = member.name, destinationID = member.serverID }; //SendeTeil Package sendPackage = new Package(hierarchie); Package recievePackage; recievePackage = Send(sendPackage, KnownServers.Root); if (recievePackage != null) { switch (recievePackage.hierarchie.HierarchieAnswer) { case HierarchieAnswer.Success: writeResult(Request.Success, InviteSuccess); break; case HierarchieAnswer.Failure: writeResult(Request.Failure, InviteFail); break; default: writeResult(Request.Failure, InviteFail); break; } } else { writeResult(Request.Error, Error); } } } } break; case Request.AnswerInvite: //TODO für P2P und Hierarchisch database.AnswerInvite(package.kaEvents[0], package.user.name, package.answerInvite); break; default: Console.WriteLine(RequestUnknown); break; } return(package); void writeResult(Request request, string line) { Console.WriteLine(line); package.request = request; } }
/// <summary> /// Das Handling von P2PPaketen. /// </summary> /// <param name="package"></param> /// <returns></returns> public static P2PPackage ResolveP2P(P2PPackage package) { if (ServerConfig.CheckPackageID(package.GetPackageID())) { try { List <P2PPackage> returnList; switch (package.P2Prequest) { case P2PRequest.NewServer: //0. Falls ich ihn noch nicht als Nachbarn habe. if (!ServerConfig.neighbours.Exists(x => x.ToString() == package.GetSource())) { //1. Anzahl Verbindungen (s. neighbours) if (package.anzConn == P2PPackage.AnzConnInit || package.anzConn > ServerConfig.neighbours.Count) { //Wenn das Paket noch nicht angefasst wurde, oder wir ein mind. genausogutes Angebot haben geht es als Antwort zurück. package.anzConn = ServerConfig.neighbours.Count; package.lastIP = ServerConfig.host.ToString(); } else if (package.anzConn == ServerConfig.neighbours.Count) { package.lastIP = ServerConfig.host.ToString(); } } //2. Test on TTL if (package.DecrementTTL() == 0) { package.P2PAnswer = P2PAnswer.Timeout; break; } //3. Forking to other servers via flooding returnList = Forward(); //Comparing answers foreach (P2PPackage p in returnList) { if (p.P2PAnswer == P2PAnswer.Error) { package.ErrorMsg = GenerateErrorString(); /*package.Exception = p.Exception;*/ } else if (package.anzConn >= p.anzConn) { package.anzConn = p.anzConn; package.lastIP = p.lastIP; } } break; case P2PRequest.RegisterServer: //1. Nimm Server in neighbours auf. (Falls noch nicht existent) if (!ServerConfig.neighbours.Exists(x => x.ToString() == package.GetSource())) { ServerConfig.neighbours.Add(IPAddress.Parse(package.GetSource())); package.P2PAnswer = P2PAnswer.Success; } else { package.P2PAnswer = P2PAnswer.Visited; } break; case P2PRequest.NewUser: //0. Existiert der User? if (ServerLogic.database.UserExist(package.GetUsername())) { package.P2PAnswer = P2PAnswer.UserExistent; break; } //1. Anzahl User int anzUser = ServerLogic.database.GetUserCount(); if (package.anzUser == P2PPackage.AnzUserInit || package.anzUser > anzUser) { // siehe case NewServer package.anzUser = anzUser; package.lastIP = ServerConfig.host.ToString(); } else if (package.anzUser == anzUser) { package.lastIP = ServerConfig.host.ToString(); } //2. Test on TTL ???? -> Nein! Nicht vereinbar mit nur einem User im gesamten Netz. /*if (package.DecrementTTL() == 0) * { * package.P2PAnswer = P2PAnswer.Timeout; * break; * }*/ //3. Forking to other servers via flooding returnList = Forward(); //Comparing answers foreach (P2PPackage p in returnList) { if (p.P2PAnswer == P2PAnswer.Error) { package.ErrorMsg = p.ErrorMsg; /*package.Exception = p.Exception;*/ package.P2PAnswer = P2PAnswer.Error; return(package); } else if (package.anzUser >= p.anzUser) { package.anzUser = p.anzUser; package.lastIP = p.lastIP; } } package.P2PAnswer = P2PAnswer.Success; break; /* * case P2PRequest.RegisterUser: * //Client should connect directly to register. * break; */ case P2PRequest.Login: //1. Check Datenbank nach user if (!ServerLogic.database.UserExist(package.GetUsername())) //2. Wenn nicht gefunden => weiterleiten { returnList = Forward(); //Falls nur ein return => Success if (returnList.Count == 1) { package.P2PAnswer = returnList.First().P2PAnswer; package.lastIP = returnList.First().lastIP; } else if (returnList.Count > 1) { foreach (P2PPackage p in returnList) { if (p.P2PAnswer == P2PAnswer.Success) { package.lastIP = p.lastIP; } } } else { package.P2PAnswer = P2PAnswer.Failure; //Error? } } else { package.lastIP = ServerConfig.host.ToString(); package.P2PAnswer = P2PAnswer.Success; } break; case P2PRequest.Invite: //1. Check Datenbank nach user if (!ServerLogic.database.UserExist(package.GetUsername())) //2. Wenn nicht gefunden => weiterleiten { returnList = Forward(); foreach (P2PPackage p in returnList) { if (p.P2PAnswer == P2PAnswer.Success) { package.P2PAnswer = p.P2PAnswer; package.lastIP = p.lastIP; } } } else { ServerLogic.database.SaveInvites(package.GetUsername(), package.GetInvite()); package.lastIP = ServerConfig.host.ToString(); package.P2PAnswer = P2PAnswer.Success; } break; default: break; } } catch (Exception ex) { Console.WriteLine(ex.Message); package.P2PAnswer = P2PAnswer.Error; package.ErrorMsg = GenerateErrorString(ex); /*package.Exception = ex;*/ //throw; } } else { package.P2PAnswer = P2PAnswer.Visited; //Node wurde bereits angefragt, keine Aktion nötig } return(package); List <P2PPackage> Forward() { Package sendPackage = new Package(package); Package recievePackage; List <P2PPackage> returnList = new List <P2PPackage>(); foreach (IPAddress iPAddress in ServerConfig.neighbours) { recievePackage = ServerLogic.Send(sendPackage, iPAddress); if (recievePackage != null) { if (recievePackage != null && recievePackage.p2p.P2PAnswer == P2PAnswer.Success) { return new List <P2PPackage>() { recievePackage.p2p } } ; returnList.Add(recievePackage.p2p); } } return(returnList); } }