
    Ki                         S r SSKrSSKrSSKrSSKrSSKrSSKJr  SSKJ	r	  SSK
JrJr  SSKrSSKJr  SSKJrJr  SS	KJr  \R*                  " S
5      r\ " S S5      5       r " S S5      rg)z(WebSocket server for client connections.    N)	dataclass)Path)Callable	Coroutine)ValidationError)serveServerConnection   )SERVER_TO_CLIENT_PACKET_ADAPTERzplaypalace.packetsc                       \ rS rSr% Sr\\S'   \\S'   Sr\S-  \S'   Sr	\
\S'   Sr\
\S	'   S
r\\S'   S
r\\S'   S\SS4S jrSS jrSrg)ClientConnection   zRepresents a connected client.	websocketaddressNusernameFauthenticatedreplaced client_typeplatformpacketreturnc                 \  #     [         R                  " U5      nUR                  SS9n U R                  R                  [        R                  " U5      5      I Sh  vN   g! [         aQ  nU R                  =(       d    U R
                  n[        R                  SUR                  SS5      UU5         SnAgSnAff = f Nc! [        R                  R                   aI    U R                  =(       d    U R
                  n[        R!                  SUR                  SS5      U5         gf = f7f)zSend a packet to this client.T)exclude_nonez3Refusing to send invalid packet (type=%s) to %s: %stype?Nz0Dropped packet type=%s to disconnected client %s)r   validate_python
model_dumpr   r   r   PACKET_LOGGERwarninggetr   sendjsondumps
websockets
exceptionsConnectionCloseddebug)selfr   packet_modelpayloadexc
identifiers         >c:\Users\dbart\PlayPalace11\server\network\websocket_server.pyr"   ClientConnection.send!   s     	:JJ6RL"--4-@G	..%%djj&9:::  	6$,,J!!E

63'	 	 ;$$55 	6$,,JBFC(	s_   D,%A" 2C C C !D,"
B=,AB83D,8B==D, C A$D)&D,(D))D,c                    #     U R                   R                  5       I Sh  vN   g N! [        [        [        R
                  R                  4 a   n[        R                  SU5         SnAgSnAff = f7f)zClose this connection.NzFailed to close websocket: %s)	r   closeOSErrorRuntimeErrorr%   r&   r'   r   r(   )r)   r,   s     r.   r1   ClientConnection.close:   sY     	F..&&(((z'<'<'M'MN 	F ?EE	Fs7   A5) ') A5) )A2A-(A5-A22A5 r   N)__name__
__module____qualname____firstlineno____doc__r	   __annotations__strr   r   boolr   r   r   dictr"   r1   __static_attributes__r5       r.   r   r      s_    (LHcDjM4HdKHc $ 2FrA   r   c                   B   \ rS rSrSr        SS\S\S\\/\	4   S-  S\\/\	4   S-  S\\\
/\	4   S-  S	\\-  S-  S
\\-  S-  S\S-  4S jjr\S\
\\4   4S j5       rSS jrSS jrS\SS4S jrSS\
S\S-  SS4S jjrS\S\
S\4S jrS\S\S-  4S jrSrg)WebSocketServerB   z
Async WebSocket server for handling client connections.

The server is async, but game logic is synchronous. Messages are
queued and processed synchronously, then responses are sent async.
Nhostport
on_connecton_disconnect
on_messagessl_certssl_keymax_message_sizec	           	         Xl         X l        X0l        X@l        XPl        0 U l        S U l        SU l        S U l        Xl	        U(       aa  U(       aY  [        R                  " [        R                  5      U l         U R                  R                  [        U5      [        U5      5        g g g ! [         a2  n	[!        SU SU SU	 3["        R$                  S9  ['        S5      U	eS n	A	ff = f)NFz.ERROR: Failed to load TLS certificate or key (z, z): filer
   )rE   rF   _on_connect_on_disconnect_on_message_clients_server_running_ssl_context_max_message_sizessl
SSLContextPROTOCOL_TLS_SERVERload_cert_chainr=   	Exceptionprintsysstderr
SystemExit)
r)   rE   rF   rG   rH   rI   rJ   rK   rL   r,   s
             r.   __init__WebSocketServer.__init__J   s     		%+%57 !1  #s/F/F GD-!!11#h-WN  8  -DXJbQXPYY\]`\ab !m,-s   9.B* *
C&4-C!!C&r   c                     U R                   $ )z+Get all connected clients keyed by address.)rS   )r)   s    r.   clientsWebSocketServer.clientsl   s     }}rA   c           	        #    SU l          [        U R                  U R                  U R                  U R
                  U R                  S9R                  5       I Sh  vN U l        U R
                  (       a  SOSn[        SU SU R                   SU R                   35        g NG! [         a  n[        SU R                   SU R                   SU 3[        R                  S9  UR                  [        R                  SS	4;   aG  [        S
[        R                  S9  [        SR                  U R                  S9[        R                  S9  [!        S5      UeSnAff = f7f)zStart the WebSocket server.T)rX   max_sizeNz*ERROR: Failed to bind WebSocket server on :z: rN   0   i@'  ziHint: That port is already in use. If another PlayPalace server is running, stop it or choose a new port.zATo find the process: `lsof -i :{port}` or `ss -ltnp | rg :{port}`)rF   r
   wsswszWebSocket server started on z://)rU   r   _handle_clientrE   rF   rV   rW   
__aenter__rT   r2   r]   r^   r_   errno
EADDRINUSEformatr`   )r)   r,   protocols      r.   startWebSocketServer.startq   s;    	)!&##				%%//" jlDL4 !--54,XJc$))Adii[QR7  	)<TYYKqSUVYUZ[ZZ yyU--r599]
 W^^!YY _  	 Q-S(#	)s<   E AB% B#	B% %>E #B% %
E/B)EEE c                 t  #    SU l         U R                  (       a<  U R                  R                  5         U R                  R                  5       I Sh  vN   [	        U R
                  R                  5       5       H  nUR                  5       I Sh  vN   M     U R
                  R                  5         g Na N%7f)zStop the WebSocket server.FN)rU   rT   r1   wait_closedlistrS   valuesclear)r)   clients     r.   stopWebSocketServer.stop   s     <<LL ,,**,,, 4==//12F,,.   3 - !s$   AB8B4=B8B6$B86B8r   c                   #    UR                   S    SUR                   S    3n[        XS9nX0R                  U'    U R                  (       a  U R                  U5      I Sh  vN   U  Sh  vN n [        R
                  " U5      nU R                  (       a  U R                  X55      I Sh  vN   ML  MN   NT NK N! [        R                   a9    UR                  =(       d    UR                  n[        R                  SU5         M  [         a9    UR                  =(       d    UR                  n[        R                  SU5         M  f = f
 O$! [        R                  R                    a     Of = fX R                  ;   a  U R                  U	 U R"                  (       a  U R#                  U5      I Sh  vN    gg! X R                  ;   a  U R                  U	 U R"                  (       a  U R#                  U5      I Sh  vN    f f = f7f)zHandle a client connection.r   rh   r
   )r   r   NzMalformed JSON from %sz*Unhandled error processing message from %s)remote_addressr   rS   rP   r#   loadsrR   JSONDecodeErrorr   r   r   r    r\   	exceptionr%   r&   r'   rQ   )r)   r   r   ry   messager   r-   s          r.   rl   WebSocketServer._handle_client   s    --a0193K3KA3N2OP!IG!'g	2&&v...!* g!ZZ0F''"..v>>> ( / ?++ P!'!BFNNJ!))*BJO   "(!BFNNJ!++Dj "+" $$55 		 --'MM'*""))&111 # --'MM'*""))&111 #s   9H	%E !B6"E (E,B8-E0E 2;B<-B:.B<2E 8E:B<<A	E
E >E
E 	E

E F< E0-F< /E00F< 3AH	4F75H	<AH>H?HH	r   excludec                    #    U R                   R                  5        H6  nUR                  (       d  M  X2:w  d  M  UR                  U5      I Sh  vN   M8     g N	7f)z0Broadcast a packet to all authenticated clients.N)rS   rw   r   r"   )r)   r   r   ry   s       r.   	broadcastWebSocketServer.broadcast   sB     mm**,F###(9kk&))) -)s   -AAAA
Ar   c                    #    U R                   R                  5        H.  nUR                  U:X  d  M  UR                  U5      I Sh  vN     g   g N	7f)z!Send a packet to a specific user.NTF)rS   rw   r   r"   )r)   r   r   ry   s       r.   send_to_userWebSocketServer.send_to_user   sG     mm**,F(*kk&))) -  *s   ,AAA
Ac                 n    U R                   R                  5        H  nUR                  U:X  d  M  Us  $    g)zGet a client by username.N)rS   rw   r   )r)   r   ry   s      r.   get_client_by_username&WebSocketServer.get_client_by_username   s/    mm**,F(* - rA   )
rS   rW   rP   rQ   rR   rU   rT   rV   rE   rF   )z::i@  NNNNNNr6   )N)r7   r8   r9   r:   r;   r=   intr   r   r   r?   r   ra   propertyrd   rr   rz   r	   rl   r   r>   r   r   r@   r5   rA   r.   rC   rC   B   sa    EIHLKO&*%)'+ - -  - ./:;dB	 -
  !1 2I =>E - .5y@ADH - *t# - td" - * -D c#334   SD
!2.> !24 !2F*d *5E5L *X\ *3   s 7G$7N rA   rC   )r;   rn   r#   loggingrX   r^   dataclassesr   pathlibr   typingr   r   r%   pydanticr   websockets.asyncio.serverr   r	   packet_modelsr   	getLoggerr   r   rC   r5   rA   r.   <module>r      sf    .    
 
 !  &  $ = :!!"67 )F )F )FXS SrA   