/// <summary> /// Server selection packet processing. /// 서버 선택 패킷 /// </summary> /// <param name="client"></param> /// <param name="buffer"></param> private void SelectedServer(cltSession client, Byte[] buffer) { //22패킷(za 정보: ip, port, new uid) 넘겨주고 접속자 정보의 기존uid를 새 uid로 변경하기. short ServerID = buffer[10]; if (g_Config.ZoneAgentList.ContainsKey(ServerID)) { PrintLogs(string.Format("<CT>ServerID={0}", ServerID)); var User = g_Config.LoggedInList.First(x => x.Value.PCID == client.PCID); zaSession zAgent = g_Config.ZoneAgentList[ServerID]; //ZS용 UID발급 uint zs_PCID = g_Config.za_Uid.Uid; PrintPCID(g_Config.za_Uid.dspUid); //유저가 몇번 서버로 이동하는지 기록함. 응답 패킷에는 서버 번호가 없으므로 여기서 미리 변경 User.Value.ServerID = ServerID; //za에게 유저 정보 넘기기 zAgent.Send(Packet.PreparedAccount(zs_PCID, User.Key)); //클라에게 za정보 넘기기 client.Send(Packet.ZoneAgentInfo(client.PCID, zs_PCID, zAgent.IPadress, zAgent.Port, client.Ver)); //za에 유저가 정상 접속한다면 za에서 답패킷(1f,02,e3)이 날아옴 g_Config.inZoneAgent++; client.Step = "ZA"; } else { PrintLogs(string.Format("<CT>ServerID={0} but ZoneAgent is Down", ServerID)); } }
/// <summary> /// In-game user account validity check: Expiration User enforcement logout. /// 게임 접속상태에서 계정 유효기한이 지난 사용자를 로그아웃 처리 /// </summary> private void CheckExpiredAccount(object sender) { if (g_Config.isExpiration) { for (int i = g_Config.LoggedInList.Count - 1; i >= 0; i--) { string strID = g_Config.LoggedInList.ElementAt(i).Key; if (DateTime.Now >= Acc_DB.getExpireDate(strID)) { if (g_Config.LoggedInList[strID].PCID > g_Config.za_Uid.MinValue) { zaSession zAgent = g_Config.ZoneAgentList[g_Config.LoggedInList[strID].ServerID]; zAgent.Send(Packet.reqDisconnectAcc(g_Config.LoggedInList[strID].PCID, strID)); PrintLogs(string.Format("request userdrop {0} {1} to zoneagent", g_Config.LoggedInList[strID].PCID, strID)); } PrintLogs(string.Format("ExpiredAccount.destroy {0}", strID)); g_Config.LoggedInList.Remove(strID); } Thread.Sleep(200); } } }
/// <summary> /// Handling login packets. /// 로그인 요청 패킷 처리 /// </summary> /// <param name="client"></param> /// <param name="buffer"></param> private void ReqUserLogin(cltSession client, Byte[] buffer) { string str_id = Packet.Bytes2String(buffer, 0x0A); string str_pwd = Packet.Bytes2String(buffer, 0x1F); //check blank if (string.IsNullOrEmpty(str_id) || string.IsNullOrEmpty(str_pwd)) { client.Send(Packet.SayMessage(g_Config.Msg_Incorrect, client.PCID, 0, client.Ver)); RemoveClient(client, true, true); #if DEBUG PrintLogs(string.Format("BlankID/PWD: RemoveClient({0})", client.PCID)); #endif } else { //get db info by account AccountInfo AccInfo = Acc_DB.getAccountInfo(str_id); if (string.IsNullOrEmpty(AccInfo.id)) { client.Send(Packet.SayMessage(g_Config.Msg_Incorrect, client.PCID, 0, client.Ver)); RemoveClient(client, true, true); #if DEBUG PrintLogs(string.Format("Wrong ID: RemoveClient({0})", client.PCID)); #endif } else { //check pwd if (!Hasher.Verify(str_pwd, AccInfo.pwd, (HashType)g_Config.hashType)) { client.Send(Packet.SayMessage(g_Config.Msg_Incorrect, client.PCID, 0, client.Ver)); RemoveClient(client, true, true); #if DEBUG PrintLogs(string.Format("Wrong PWD: RemoveClient({0})", client.PCID)); #endif } else { //check status if (g_Config.RejectDB.ContainsKey(AccInfo.status)) { client.Send(Packet.SayMessage(g_Config.RejectDB[AccInfo.status], client.PCID, 3, client.Ver)); RemoveClient(client, true, false); #if DEBUG PrintLogs(string.Format("StatusReject: RemoveClient({0})", client.PCID)); #endif } else { #if DEBUG PrintLogs(string.Format("{0} ExpireDate: {1}", AccInfo.id, AccInfo.expDate)); #endif //check expire if (g_Config.isExpiration && DateTime.Now >= AccInfo.expDate) { client.Send(Packet.SayMessage(g_Config.Msg_Expired, client.PCID, 3, client.Ver)); RemoveClient(client, true, false); } else { //log-in succeed: check duplicate connections if (!g_Config.LoggedInList.ContainsKey(str_id)) { string msg = string.Empty; //아직 서버 선택전이므로 로그인 유저 정보의 Sid = -1로 설정함 g_Config.LoggedInList.Add(str_id, new LoginUser(client.PCID, -1)); if (g_Config.isExpiration) { TimeSpan ts = AccInfo.expDate - DateTime.Now; msg = string.Format(g_Config.Msg_ExpireInfo, ts.Days, ts.Hours, ts.Minutes); } client.Send(Packet.CreateSvrList(client.PCID, client.Ver, g_Config.ZoneAgentList, g_Config.ServerList, msg)); PrintLogs(string.Format("SuccLogin: {0}:{1} {2}", client.IPadress, client.Port, str_id)); #if DEBUG PrintLogs(string.Format("RegLoginUser: {0}", str_id)); #endif } else { //duplication act: in LA OR in ZA - uid가 ZaUID의 최소값(65535)이상이면 이미 za로 넘어간 유저 PrintLogs(string.Format("Duplicate login detected {0} {1}", g_Config.LoggedInList[str_id].PCID, str_id)); //za 유저인경우 za에게 디스커넥트 요청을 해야함: 완료시 30패킷을 되돌려받음 if (g_Config.LoggedInList[str_id].PCID > g_Config.za_Uid.MinValue) { zaSession zAgent = g_Config.ZoneAgentList[g_Config.LoggedInList[str_id].ServerID]; zAgent.Send(Packet.reqDisconnectAcc(g_Config.LoggedInList[str_id].PCID, str_id)); PrintLogs(string.Format("Request UserDrop {0} {1} to ZoneAgent", g_Config.LoggedInList[str_id].PCID, str_id)); } g_Config.LoggedInList.Remove(str_id); PrintLogs(string.Format("Previous LoggedInUser.destroy {0}", str_id)); client.Send(Packet.SayMessage(g_Config.Msg_Duplication, client.PCID, 2, client.Ver)); RemoveClient(client, true, false); } } } } } } }