|  |  |  | @ -10,6 +10,7 @@ import ( | 
		
	
		
			
				|  |  |  |  | 	"reflect" | 
		
	
		
			
				|  |  |  |  | 	"sync" | 
		
	
		
			
				|  |  |  |  | 	"sync/atomic" | 
		
	
		
			
				|  |  |  |  |   "time" | 
		
	
		
			
				|  |  |  |  | ) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | const ( | 
		
	
	
		
			
				
					|  |  |  | @ -19,6 +20,7 @@ const ( | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | type ServerSession struct { | 
		
	
		
			
				|  |  |  |  |   Session | 
		
	
		
			
				|  |  |  |  |   LastSeen time.Time | 
		
	
		
			
				|  |  |  |  |   IncomingPackets chan[]byte | 
		
	
		
			
				|  |  |  |  |   OutgoingPackets chan *Packet | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | @ -160,6 +162,7 @@ func(server *Server) listen_udp() { | 
		
	
		
			
				|  |  |  |  |         server.sessions_lock.Lock() | 
		
	
		
			
				|  |  |  |  |         server.sessions[session.ID] = &ServerSession{ | 
		
	
		
			
				|  |  |  |  |           Session: session, | 
		
	
		
			
				|  |  |  |  |           LastSeen: time.Now(), | 
		
	
		
			
				|  |  |  |  |           IncomingPackets: make(chan[]byte, SESSION_BUFFER_SIZE), | 
		
	
		
			
				|  |  |  |  |           OutgoingPackets: make(chan *Packet, SESSION_BUFFER_SIZE), | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
	
		
			
				
					|  |  |  | @ -264,6 +267,7 @@ func(server *Server) listen_udp() { | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         session.remote = client_addr | 
		
	
		
			
				|  |  |  |  |         session.LastSeen = time.Now() | 
		
	
		
			
				|  |  |  |  |          | 
		
	
		
			
				|  |  |  |  |         // TODO: Make a better server hello
 | 
		
	
		
			
				|  |  |  |  |         server_hello, err := NewSessionData(&session.Session, []byte("hello")) | 
		
	
	
		
			
				
					|  |  |  | @ -293,11 +297,8 @@ func(server *Server) listen_udp() { | 
		
	
		
			
				|  |  |  |  |           continue | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         close(session.IncomingPackets) | 
		
	
		
			
				|  |  |  |  |         close(session.OutgoingPackets) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         server.sessions_lock.Lock() | 
		
	
		
			
				|  |  |  |  |         delete(server.sessions, session_id) | 
		
	
		
			
				|  |  |  |  |         server.close_session(session) | 
		
	
		
			
				|  |  |  |  |         server.sessions_lock.Unlock() | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         server.Log("Session %s closed", session_id) | 
		
	
	
		
			
				
					|  |  |  | @ -310,6 +311,8 @@ func(server *Server) listen_udp() { | 
		
	
		
			
				|  |  |  |  |           continue | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         session.LastSeen = time.Now() | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |         buf_copy := make([]byte, read - COMMAND_LENGTH - ID_LENGTH) | 
		
	
		
			
				|  |  |  |  |         copy(buf_copy, buf[COMMAND_LENGTH+ID_LENGTH:read]) | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -330,10 +333,12 @@ func(server *Server) listen_udp() { | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   server.sessions_lock.Lock() | 
		
	
		
			
				|  |  |  |  |   for session_id, session := range(server.sessions) { | 
		
	
		
			
				|  |  |  |  |     close(session.IncomingPackets) | 
		
	
		
			
				|  |  |  |  |     close(session.OutgoingPackets) | 
		
	
		
			
				|  |  |  |  |     delete(server.sessions, session_id) | 
		
	
		
			
				|  |  |  |  |   sessions := make([]*ServerSession, 0, len(server.sessions)) | 
		
	
		
			
				|  |  |  |  |   for _, session := range(server.sessions) {   | 
		
	
		
			
				|  |  |  |  |     sessions = append(sessions, session) | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   for _, session := range(sessions) { | 
		
	
		
			
				|  |  |  |  |     server.close_session(session) | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  |   server.sessions_lock.Unlock() | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
	
		
			
				
					|  |  |  | @ -342,7 +347,7 @@ func(server *Server) listen_udp() { | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(server *Server) send_sessions() { | 
		
	
		
			
				|  |  |  |  |   for true { | 
		
	
		
			
				|  |  |  |  |   for server.active.Load() { | 
		
	
		
			
				|  |  |  |  |     packets := <- server.send_packets  | 
		
	
		
			
				|  |  |  |  |     if packets == nil { | 
		
	
		
			
				|  |  |  |  |       break | 
		
	
	
		
			
				
					|  |  |  | @ -359,6 +364,40 @@ func(server *Server) send_sessions() { | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(server *Server) close_session(session *ServerSession) { | 
		
	
		
			
				|  |  |  |  |   close(session.IncomingPackets) | 
		
	
		
			
				|  |  |  |  |   close(session.OutgoingPackets) | 
		
	
		
			
				|  |  |  |  |   delete(server.sessions, session.ID) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | const SESSION_TIMEOUT = time.Minute * 5 | 
		
	
		
			
				|  |  |  |  | const SESSION_TIMEOUT_CHECK = time.Minute | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(server *Server) cleanup_sessions() { | 
		
	
		
			
				|  |  |  |  |   for server.active.Load() { | 
		
	
		
			
				|  |  |  |  |     select { | 
		
	
		
			
				|  |  |  |  |     case <-time.After(SESSION_TIMEOUT_CHECK): | 
		
	
		
			
				|  |  |  |  |       server.Log("Running stale session check") | 
		
	
		
			
				|  |  |  |  |       server.sessions_lock.Lock() | 
		
	
		
			
				|  |  |  |  |       now := time.Now() | 
		
	
		
			
				|  |  |  |  |       stale_sessions := make([]*ServerSession, 0, len(server.sessions)) | 
		
	
		
			
				|  |  |  |  |       for _, session := range(server.sessions) { | 
		
	
		
			
				|  |  |  |  |         if now.Sub(session.LastSeen) >= SESSION_TIMEOUT { | 
		
	
		
			
				|  |  |  |  |           server.Log("Closing stale session %s for %s", session.ID, session.Peer) | 
		
	
		
			
				|  |  |  |  |           stale_sessions = append(stale_sessions, session) | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       for _, session := range(stale_sessions) { | 
		
	
		
			
				|  |  |  |  |         server.close_session(session) | 
		
	
		
			
				|  |  |  |  |       } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |       server.sessions_lock.Unlock() | 
		
	
		
			
				|  |  |  |  |     // TODO: add a way for this to be shutdown instantly on server shutdown
 | 
		
	
		
			
				|  |  |  |  |     } | 
		
	
		
			
				|  |  |  |  |   } | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  | func(server *Server) Start(listen string) error { | 
		
	
		
			
				|  |  |  |  |   was_inactive := server.active.CompareAndSwap(false, true) | 
		
	
		
			
				|  |  |  |  |   if was_inactive == false { | 
		
	
	
		
			
				
					|  |  |  | @ -379,6 +418,7 @@ func(server *Server) Start(listen string) error { | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   go server.listen_udp() | 
		
	
		
			
				|  |  |  |  |   go server.send_sessions() | 
		
	
		
			
				|  |  |  |  |   go server.cleanup_sessions() | 
		
	
		
			
				|  |  |  |  | 
 | 
		
	
		
			
				|  |  |  |  |   return nil | 
		
	
		
			
				|  |  |  |  | } | 
		
	
	
		
			
				
					|  |  |  | 
 |