/// <summary> /// sends a sessioninfopacket to the client /// </summary> /// <param name="sessioninfo">the sessioninfo which is supposed to be sent</param> public void sendSessionInfo(headers.infotype sessioninfo) { try { sendrecv.sendStartPattern(writer); sendrecv.writeOnStream(writer, new byte[] { headers.packettypebytes[headers.packettype.SessionInfo] }); sendrecv.writeOnStream(writer, new byte[] { headers.infotypebytes[sessioninfo] }); } catch (Exception ex) { if (ex is ConnectionNotWorkingException) { stopAsyncListening(); // not calling handleconnetionproblems here, because it would call it would cause a stack overflow //because that method calls eventually session.delete which calls this method again } } }
/// <summary> /// continuesly waits for a new packet and calls depending on the packet type a method to handle /// the packet. /// only stops when an exception occurs or when the Asyncreadflag is set to false. /// </summary> private void reading() { try { while (Asyncreadflag) { //wait for a new packet sendrecv.waitforstartpattern(reader); headers.packettype type = headers.packettypes[sendrecv.readfromstream(reader, 1)[0]]; //check the type of the packet //if packet is not a sessioninfo packet forward it without looking at it if (type != headers.packettype.SessionInfo) { Int32 datalength = BitConverter.ToInt32(sendrecv.readfromstream(reader, 4), 0); byte[] data = sendrecv.readfromstream(reader, datalength); foreach (Client c in session.clients) { if (c.role != this.role) { c.forward(type, data); break; } } } //if the packet is a session info packet, the information is processed by the method handlesessioninfo else if (type == headers.packettype.SessionInfo) { headers.infotype infotype = headers.infotypes[sendrecv.readfromstream(reader, 1)[0]]; handlesessioninfo(infotype); } } } catch (Exception ex) { //ignore all exceptions after the moment this thread is supposed to end if (Asyncreadflag) { Console.WriteLine( $"Error in async reading for {role.ToString()} in session {this.session.SessionID}: {ex.Message}"); } } }
/// <summary> /// this method handles received session info packets /// </summary> /// <param name="infotype"> /// the type of the packet that is supposed to be processed /// </param> private void handlesessioninfo(headers.infotype infotype) { //now forward the sessioninfo to the other client in the session foreach (var c in session.clients) { if (infotype == headers.infotype.EndSession) { break; //don't forward endsession yet, because that is handled later } if (c.role != this.role) { c.forward(headers.packettype.SessionInfo, new byte[] { headers.infotypebytes[infotype] }); } } switch (infotype) { case headers.infotype.EndSession: //moderator ended session -> delete the entire session Console.WriteLine("[-] SessionEnd requested"); Asyncreadflag = false; sendstring("ok"); //signalize client, that the message was received, so the connection can be closed from both sides session.removeClient(this); SessionManager.Instance.delete(session); return; case headers.infotype.QuitSession: //viewer quit session -> remove this client from the session sendstring("ok"); stopAsyncListening(); session.removeClient(this); break; case headers.infotype.RequestAccepted: //a "get-Moderator" - Request was accepted -> toggle the roles of both clients foreach (Client c in session.clients) { c.toggleRole(); c.sendCurrentSessionInfo(); } break; } }
/// <summary> /// handles a sessioninfo packet /// </summary> private void handlesessioninfo() { headers.infotype infotype = headers.infotypes[sendrecv.readfromstream(_Reader, 1)[0]]; //first get the infotype of the sessioninfopacket //handle the packet depending on the type of the packet switch (infotype) { case headers.infotype.CurrentSessionInfo: Int32 idlength = BitConverter.ToInt32(sendrecv.readfromstream(_Reader, 4), 0); string id = Encoding.UTF8.GetString(sendrecv.readfromstream(_Reader, idlength)); byte role = sendrecv.readfromstream(_Reader, 1)[0]; this.Role = role == 0 ? delegates.Roles.Moderator : delegates.Roles.Viewer; SessionInfoAvailable.Invoke(id, role == 0 ? delegates.Roles.Moderator : delegates.Roles.Viewer); break; case headers.infotype.EndSession: stopAsyncRead(); SessionEnded.Invoke(); break; case headers.infotype.ViewerJoined: ViewerJoinedSession.Invoke(); break; case headers.infotype.QuitSession: ViewerQuitSession.Invoke(); break; case headers.infotype.RequestModerator: ModeratorRequest.Invoke(); break; case headers.infotype.RequestDenied: RequestAnswerAvailable.Invoke(false); break; case headers.infotype.RequestAccepted: RequestAnswerAvailable.Invoke(true); break; } }