Skip to content

Commit 992a691

Browse files
allow any core message even if no session has been established (#67)
1 parent 02e9062 commit 992a691

6 files changed

Lines changed: 491 additions & 137 deletions

File tree

etpproto/client_info.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class ClientInfo:
2626
)
2727
login: str = field(default="anonymousUser")
2828
ip: str = field(default="0.0.0.0")
29+
authenticated: bool = field(default=False)
2930

3031
def __post_init__(self):
3132
self._id = self.count_instance

etpproto/connection.py

Lines changed: 166 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@
2929
from etptypes.energistics.etp.v12.protocol.core.close_session import (
3030
CloseSession,
3131
)
32+
from etptypes.energistics.etp.v12.protocol.core.authorize_response import (
33+
AuthorizeResponse,
34+
)
35+
from etptypes.energistics.etp.v12.protocol.core.authorize import Authorize
3236
from etptypes.energistics.etp.v12.protocol.core.open_session import OpenSession
3337
from etptypes.energistics.etp.v12.protocol.core.request_session import (
3438
RequestSession,
@@ -41,6 +45,8 @@
4145
InvalidMessageError,
4246
UnsupportedProtocolError,
4347
NotSupportedError,
48+
InvalidStateError,
49+
AuthorizationRequired,
4450
)
4551
from etpproto.messages import Message
4652
from etpproto.utils import ProtocolDict, get_all_etp_protocol_classes
@@ -136,6 +142,8 @@ class ETPConnection:
136142

137143
is_connected: bool = field(default=False)
138144

145+
auth_required: bool = field(default=False)
146+
139147
message_id: int = field(default=1)
140148

141149
# ______ __ __ ________ __
@@ -164,6 +172,7 @@ def __post_init__(self):
164172
self.message_id = 1
165173
elif self.connection_type == ConnectionType.CLIENT:
166174
self.message_id = 2
175+
self.auth_required = False # auth is only required on server side
167176

168177
def _handle_answer_and_error(
169178
self,
@@ -189,158 +198,182 @@ async def _handle_message_generator(
189198
if (
190199
etp_input_msg is not None and etp_input_msg.header is not None
191200
): # si pas un message none
192-
if (
193-
isinstance(etp_input_msg.body, RequestSession)
194-
or isinstance(etp_input_msg.body, OpenSession)
195-
or self.is_connected
201+
if not self.auth_required or (
202+
self.client_info is not None
203+
and (
204+
self.client_info.authenticated
205+
or (
206+
isinstance(etp_input_msg.body, Authorize)
207+
or isinstance(etp_input_msg.body, AuthorizeResponse)
208+
)
209+
)
196210
):
197-
current_msg_id = etp_input_msg.header.message_id
198-
199-
# if requires acknowledge :
200-
if etp_input_msg.is_asking_acknowledge() and not isinstance(
201-
etp_input_msg.body, Acknowledge
211+
if (
212+
# isinstance(etp_input_msg.body, RequestSession)
213+
# or isinstance(etp_input_msg.body, OpenSession)
214+
etp_input_msg.header.protocol
215+
== CommunicationProtocol.CORE.value
216+
or self.is_connected
202217
):
203-
yield Message.get_object_message(
204-
Acknowledge(),
205-
correlation_id=current_msg_id,
206-
msg_id=self.consume_msg_id(),
207-
)
208-
# time.sleep(3)
209-
210-
# only if the user is connected or request for an OpenSession or if the message is not the full message
218+
current_msg_id = etp_input_msg.header.message_id
211219

212-
if self.is_connected and isinstance(
213-
etp_input_msg.body, CloseSession
214-
):
215-
logging.debug(
216-
f"{self.client_info.ip} : CloseSession recieved"
217-
)
218-
self.is_connected = False
219-
else:
220-
# Test if it is an Open/Request session
220+
# if requires acknowledge :
221221
if (
222-
isinstance(etp_input_msg.body, RequestSession)
223-
and self.connection_type == ConnectionType.SERVER
224-
) or (
225-
isinstance(etp_input_msg.body, OpenSession)
226-
and self.connection_type == ConnectionType.CLIENT
222+
etp_input_msg.is_asking_acknowledge()
223+
and not isinstance(etp_input_msg.body, Acknowledge)
227224
):
228-
self.is_connected = True
229-
self.client_info.negotiate(etp_input_msg.body)
230-
231-
# logging.debug(etp_input_msg, etp_input_msg.is_chunk_msg(), etp_input_msg.is_chunk_msg_referencer())
232-
# On test si c'est un message de BLOB qu'il faut mettre en cache :
233-
if etp_input_msg.is_multipart_msg() and (
234-
etp_input_msg.is_chunk_msg()
235-
or etp_input_msg.is_chunk_msg_referencer()
225+
yield Message.get_object_message(
226+
Acknowledge(),
227+
correlation_id=current_msg_id,
228+
msg_id=self.consume_msg_id(),
229+
)
230+
# time.sleep(3)
231+
232+
# only if the user is connected or request for an OpenSession or if the message is not the full message
233+
234+
if self.is_connected and isinstance(
235+
etp_input_msg.body, CloseSession
236236
):
237-
cache_id = (
238-
etp_input_msg.header.correlation_id
239-
if etp_input_msg.header.correlation_id != 0
240-
else etp_input_msg.header.message_id
237+
logging.debug(
238+
f"{self.client_info.ip} : CloseSession recieved"
241239
)
242-
if cache_id not in self.chunk_msg_cache:
243-
self.chunk_msg_cache[cache_id] = []
244-
self.chunk_msg_cache[cache_id].append(etp_input_msg)
245-
246-
# si final on rassemble et on handle.
247-
if etp_input_msg.is_final_msg():
248-
logging.debug(
249-
f"Reassemble chunks :{self.chunk_msg_cache[cache_id]}",
240+
self.is_connected = False
241+
else:
242+
# Test if it is an Open/Request session
243+
if (
244+
isinstance(etp_input_msg.body, RequestSession)
245+
and self.connection_type == ConnectionType.SERVER
246+
) or (
247+
isinstance(etp_input_msg.body, OpenSession)
248+
and self.connection_type == ConnectionType.CLIENT
249+
):
250+
self.is_connected = True
251+
self.client_info.negotiate(etp_input_msg.body)
252+
253+
# logging.debug(etp_input_msg, etp_input_msg.is_chunk_msg(), etp_input_msg.is_chunk_msg_referencer())
254+
# On test si c'est un message de BLOB qu'il faut mettre en cache :
255+
if etp_input_msg.is_multipart_msg() and (
256+
etp_input_msg.is_chunk_msg()
257+
or etp_input_msg.is_chunk_msg_referencer()
258+
):
259+
cache_id = (
260+
etp_input_msg.header.correlation_id
261+
if etp_input_msg.header.correlation_id != 0
262+
else etp_input_msg.header.message_id
263+
)
264+
if cache_id not in self.chunk_msg_cache:
265+
self.chunk_msg_cache[cache_id] = []
266+
self.chunk_msg_cache[cache_id].append(
267+
etp_input_msg
250268
)
269+
270+
# si final on rassemble et on handle.
271+
if etp_input_msg.is_final_msg():
272+
logging.debug(
273+
f"Reassemble chunks :{self.chunk_msg_cache[cache_id]}",
274+
)
275+
try:
276+
async for msg in self._handle_message_generator(
277+
Message.reassemble_chunk(
278+
self.chunk_msg_cache[cache_id]
279+
)
280+
):
281+
if msg is not None:
282+
yield msg
283+
else:
284+
if (
285+
cache_id
286+
not in self.error_msg_cache
287+
):
288+
self.error_msg_cache[
289+
cache_id
290+
] = []
291+
self.error_msg_cache[
292+
cache_id
293+
].append(
294+
InvalidMessageError().to_etp_message(
295+
msg_id=self.consume_msg_id()
296+
)
297+
)
298+
299+
except Exception as e:
300+
logging.error(
301+
f"{self.client_info.ip}: _SERVER_ not handled exception",
302+
)
303+
raise e
304+
305+
if cache_id in self.error_msg_cache:
306+
for err_msg in self.error_msg_cache[
307+
cache_id
308+
]:
309+
if err_msg is not None:
310+
yield err_msg
311+
self.error_msg_cache.pop(cache_id)
312+
313+
if cache_id in self.chunk_msg_cache:
314+
self.chunk_msg_cache.pop(cache_id)
315+
316+
else: # ce n'est pas un message envoye en chunks
317+
# now try to have an answer
251318
try:
252-
async for msg in self._handle_message_generator(
253-
Message.reassemble_chunk(
254-
self.chunk_msg_cache[cache_id]
319+
# Test si le protocol est supporte par le serveur
320+
if (
321+
CommunicationProtocol(
322+
etp_input_msg.header.protocol
255323
)
324+
in self.transition_table
256325
):
257-
if msg is not None:
258-
yield msg
259-
else:
260-
if (
261-
cache_id
262-
not in self.error_msg_cache
326+
# demande la reponse au protocols du serveur
327+
try:
328+
async for handled in self.transition_table[
329+
CommunicationProtocol(
330+
etp_input_msg.header.protocol
331+
)
332+
].handle_message(
333+
etp_object=etp_input_msg.body,
334+
msg_header=etp_input_msg.header,
335+
client_info=self.client_info,
263336
):
264-
self.error_msg_cache[cache_id] = []
265-
self.error_msg_cache[cache_id].append(
266-
InvalidMessageError().to_etp_message(
267-
msg_id=self.consume_msg_id()
337+
yield self._handle_answer_and_error(
338+
msg=handled,
339+
req_msg=etp_input_msg,
340+
request_msg_id=current_msg_id,
268341
)
342+
except ETPError as exp_invalid_msg_type:
343+
yield exp_invalid_msg_type.to_etp_message(
344+
msg_id=self.consume_msg_id(),
345+
correlation_id=current_msg_id,
269346
)
270-
271-
except Exception as e:
347+
else:
348+
logging.debug(
349+
f"{self.client_info.ip} : #handle_msg : unkown protocol id : {str(etp_input_msg.header.protocol)}"
350+
)
351+
raise UnsupportedProtocolError(
352+
etp_input_msg.header.protocol
353+
)
354+
except ETPError as etp_err:
272355
logging.error(
273-
f"{self.client_info.ip}: _SERVER_ not handled exception",
356+
f"{self.client_info.ip}: _SERVER_ internal error : {etp_err}"
274357
)
275-
raise e
276-
277-
if cache_id in self.error_msg_cache:
278-
for err_msg in self.error_msg_cache[cache_id]:
279-
if err_msg is not None:
280-
yield err_msg
281-
self.error_msg_cache.pop(cache_id)
282-
283-
if cache_id in self.chunk_msg_cache:
284-
self.chunk_msg_cache.pop(cache_id)
285-
286-
else: # ce n'est pas un message envoye en chunks
287-
# now try to have an answer
288-
try:
289-
# Test si le protocol est supporte par le serveur
290-
if (
291-
CommunicationProtocol(
292-
etp_input_msg.header.protocol
293-
)
294-
in self.transition_table
295-
):
296-
# demande la reponse au protocols du serveur
297-
try:
298-
async for handled in self.transition_table[
299-
CommunicationProtocol(
300-
etp_input_msg.header.protocol
301-
)
302-
].handle_message(
303-
etp_object=etp_input_msg.body,
304-
msg_header=etp_input_msg.header,
305-
client_info=self.client_info,
306-
):
307-
yield self._handle_answer_and_error(
308-
msg=handled,
309-
req_msg=etp_input_msg,
310-
request_msg_id=current_msg_id,
311-
)
312-
except ETPError as exp_invalid_msg_type:
313-
yield exp_invalid_msg_type.to_etp_message(
358+
yield self._handle_answer_and_error(
359+
msg=etp_err.to_etp_message(
314360
msg_id=self.consume_msg_id(),
315361
correlation_id=current_msg_id,
316-
)
317-
318-
else:
319-
logging.debug(
320-
f"{self.client_info.ip} : #handle_msg : unkown protocol id : {str(etp_input_msg.header.protocol)}"
362+
),
363+
req_msg=etp_input_msg,
364+
request_msg_id=current_msg_id,
321365
)
322-
raise UnsupportedProtocolError(
323-
etp_input_msg.header.protocol
366+
except Exception as e:
367+
logging.error(
368+
f"{self.client_info.ip}: _SERVER_ not handled exception",
324369
)
325-
except ETPError as etp_err:
326-
logging.error(
327-
f"{self.client_info.ip}: _SERVER_ internal error : {etp_err}"
328-
)
329-
yield self._handle_answer_and_error(
330-
msg=etp_err.to_etp_message(
331-
msg_id=self.consume_msg_id(),
332-
correlation_id=current_msg_id,
333-
),
334-
req_msg=etp_input_msg,
335-
request_msg_id=current_msg_id,
336-
)
337-
except Exception as e:
338-
logging.error(
339-
f"{self.client_info.ip}: _SERVER_ not handled exception",
340-
)
341-
raise e
342-
else: # not connected
343-
yield InvalidMessageError().to_etp_message(
370+
raise e
371+
else: # not connected
372+
yield InvalidStateError().to_etp_message(
373+
msg_id=self.consume_msg_id()
374+
)
375+
else: # not authenticated
376+
yield AuthorizationRequired().to_etp_message(
344377
msg_id=self.consume_msg_id()
345378
)
346379
else: # null message
@@ -445,7 +478,7 @@ def get_supported_protocol_list(
445478
) -> List[SupportedProtocol]:
446479
supported_protocols: List[SupportedProtocol] = []
447480
for protocol in cls.transition_table:
448-
if protocol.value != protocol.CORE:
481+
if protocol.value != CommunicationProtocol.CORE:
449482
supported_protocols.append(
450483
SupportedProtocol(
451484
protocol=protocol.value,

0 commit comments

Comments
 (0)