1 package OpenSRF::Transport;
2 use strict; use warnings;
5 use OpenSRF::AppSession;
6 use OpenSRF::Utils::Logger qw(:level);
7 use OpenSRF::DomainObject::oilsResponse qw/:status/;
8 use OpenSRF::EX qw/:try/;
9 use OpenSRF::Transport::SlimJabber::MessageWrapper;
12 # --- These must be implemented by all Transport subclasses
13 # -------------------------------------------
17 Returns the package name of the package the system will use to
18 gather incoming requests
22 sub get_listener { shift()->alert_abstract(); }
24 =head2 get_peer_client
26 Returns the name of the package responsible for client communication
30 sub get_peer_client { shift()->alert_abstract(); }
32 =head2 get_msg_envelope
34 Returns the name of the package responsible for parsing incoming messages
38 sub get_msg_envelope { shift()->alert_abstract(); }
40 # -------------------------------------------
42 our $message_envelope;
43 my $logger = "OpenSRF::Utils::Logger";
47 =head2 message_envelope( [$envelope] );
49 Sets the message envelope class that will allow us to extract
50 information from the messages we receive from the low
55 sub message_envelope {
56 my( $class, $envelope ) = @_;
58 $message_envelope = $envelope;
59 eval "use $envelope;";
62 "Error loading message_envelope: $envelope -> $@", ERROR);
65 return $message_envelope;
68 =head2 handler( $data )
70 Creates a new MessageWrapper, extracts the remote_id, session_id, and message body
71 from the message. Then, creates or retrieves the AppSession object with the session_id and remote_id.
72 Finally, creates the message document from the body of the message and calls
73 the handler method on the message document.
78 my( $class, $service, $data ) = @_;
80 $logger->transport( "Transport handler() received $data", INTERNAL );
82 # pass data to the message envelope
83 my $helper = OpenSRF::Transport::SlimJabber::MessageWrapper->new( $data );
85 # Extract message information
86 my $remote_id = $helper->get_remote_id();
87 my $sess_id = $helper->get_sess_id();
88 my $body = $helper->get_body();
89 my $type = $helper->get_msg_type();
92 "Transport building/retrieving session: $service, $remote_id, $sess_id", DEBUG );
94 # See if the app_session already exists. If so, make
95 # sure the sender hasn't changed if we're a server
96 my $app_session = OpenSRF::AppSession->find( $sess_id );
97 if( $app_session and $app_session->endpoint == $app_session->SERVER() and
98 $app_session->remote_id ne $remote_id ) {
99 $logger->transport( "Backend Gone or invalid sender", INTERNAL );
100 my $res = OpenSRF::DomainObject::oilsBrokenSession->new();
101 $res->status( "Backend Gone or invalid sender, Reconnect" );
102 $app_session->status( $res );
106 # Retrieve or build the app_session as appropriate (server_build decides which to do)
107 $logger->transport( "AppSession is valid or does not exist yet", INTERNAL );
108 $app_session = OpenSRF::AppSession->server_build( $sess_id, $remote_id, $service );
110 if( ! $app_session ) {
111 throw OpenSRF::EX::Session ("Transport::handler(): No AppSession object returned from server_build()");
114 # Create a document from the XML contained within the message
116 eval { $doc = OpenSRF::DOM->new->parse_string($body); };
119 $logger->transport( "Received bogus XML", INFO );
120 $logger->transport( "Bogus XML data: \n $body \n", INTERNAL );
121 my $res = OpenSRF::DomainObject::oilsXMLParseError->new( status => "XML Parse Error --- $body" );
123 $app_session->status($res);
124 #$app_session->kill_me;
128 $logger->transport( "Transport::handler() creating \n$body", INTERNAL );
130 # We need to disconnect the session if we got a jabber error on the client side. For
131 # server side, we'll just tear down the session and go away.
132 if (defined($type) and $type eq 'error') {
134 if( $app_session->endpoint == $app_session->SERVER() ) {
135 $app_session->kill_me;
139 $app_session->state( $app_session->DISCONNECTED );
140 $app_session->push_resend( $app_session->app_request( $doc->documentElement->firstChild->threadTrace ) );
145 # cycle through and pass each oilsMessage contained in the message
146 # up to the message layer for processing.
147 for my $msg ($doc->documentElement->childNodes) {
150 "Transport::handler()passing to message handler \n".$msg->toString(1), DEBUG );
153 "Transport passing up ".$msg->type." from ".
154 $app_session->remote_id . " with threadTrace [" . $msg->threadTrace."]", INFO );
156 next unless ( $msg->nodeName eq 'oils:domainObject' &&
157 $msg->getAttribute('name') eq 'oilsMessage' );
159 if( $app_session->endpoint == $app_session->SERVER() ) {
163 if( ! $msg->handler( $app_session ) ) { return 0; }
168 my $res = OpenSRF::DomainObject::oilsServerError->new();
169 $res->status( $res->status . "\n" . $e->text );
170 $logger->error($res->stringify);
171 $app_session->status($res) if $res;
172 $app_session->kill_me;
179 if( ! $msg->handler( $app_session ) ) { return 0; }