1 package OpenSRF::DomainObject::oilsMessage;
2 use base 'OpenSRF::DomainObject';
3 use OpenSRF::AppSession;
4 use OpenSRF::DomainObject::oilsResponse qw/:status/;
5 use OpenSRF::Utils::Logger qw/:level/;
6 use warnings; use strict;
7 use OpenSRF::EX qw/:try/;
11 OpenSRF::DomainObject::oilsMessage
15 use OpenSRF::DomainObject::oilsMessage;
17 my $msg = OpenSRF::DomainObject::oilsMessage->new( type => 'CONNECT' );
19 $msg->payload( $domain_object );
23 OpenSRF::DomainObject::oilsMessage is used internally to wrap data sent
24 between client and server. It provides the structure needed to authenticate
25 session data, and also provides the logic needed to unwrap session data and
26 pass this information along to the Application Layer.
30 my $log = 'OpenSRF::Utils::Logger';
34 =head2 OpenSRF::DomainObject::oilsMessage->type( [$new_type] )
38 Used to specify the type of message. One of
39 B<CONNECT, REQUEST, RESULT, STATUS, ERROR, or DISCONNECT>.
47 return $self->_attr_get_set( type => shift );
50 =head2 OpenSRF::DomainObject::oilsMessage->api_level( [$new_api_level] )
54 Used to specify the api_level of message. Currently, only api_level C<1> is
55 supported. This will be used to check that messages are well-formed, and as
56 a hint to the Application as to which version of a method should fulfill a
65 return $self->_attr_get_set( api_level => shift );
68 =head2 OpenSRF::DomainObject::oilsMessage->threadTrace( [$new_threadTrace] );
72 Sets or gets the current message sequence identifier, or thread trace number,
73 for a message. Useful as a debugging aid, but that's about it.
81 return $self->_attr_get_set( threadTrace => shift );
84 =head2 OpenSRF::DomainObject::oilsMessage->update_threadTrace
88 Increments the threadTrace component of a message. This is automatic when
89 using the normal session processing stack.
95 sub update_threadTrace {
97 my $tT = $self->threadTrace;
102 $log->debug("Setting threadTrace to $tT",DEBUG);
104 $self->threadTrace($tT);
109 =head2 OpenSRF::DomainObject::oilsMessage->payload( [$new_payload] )
113 Sets or gets the payload of a message. This should be exactly one object
114 of (sub)type domainObject or domainObjectCollection.
124 my ($payload) = $self->getChildrenByTagName('oils:domainObjectCollection') ||
125 $self->getChildrenByTagName('oils:domainObject');
127 $payload = $self->removeChild($payload) if ($payload);
128 $self->appendChild($new_pl);
129 return $new_pl unless ($payload);
132 return OpenSRF::DOM::upcast($payload)->upcast if ($payload);
135 =head2 OpenSRF::DomainObject::oilsMessage->handler( $session_id )
139 Used by the message processing stack to set session state information from the current
140 message, and then sends control (via the payload) to the Application layer.
150 my $mtype = $self->type;
151 my $api_level = $self->api_level || 1;;
152 my $tT = $self->threadTrace;
154 $session->last_message_type($mtype);
155 $session->last_message_api_level($api_level);
156 $session->last_threadTrace($tT);
158 $log->debug(" Received api_level => [$api_level], MType => [$mtype], ".
159 "from [".$session->remote_id."], threadTrace[".$self->threadTrace."]", INFO);
160 $log->debug("endpoint => [".$session->endpoint."]", DEBUG);
161 $log->debug("OpenSRF::AppSession->SERVER => [".$session->SERVER()."]", DEBUG);
165 if ( $session->endpoint == $session->SERVER() ) {
166 $val = $self->do_server( $session, $mtype, $api_level, $tT );
168 } elsif ($session->endpoint == $session->CLIENT()) {
169 $val = $self->do_client( $session, $mtype, $api_level, $tT );
173 $log->debug("Passing request up to OpenSRF::Application", DEBUG);
174 return OpenSRF::Application->handler($session, $self->payload);
176 $log->debug("Request was handled internally", DEBUG);
185 # handle server side message processing
187 # !!! Returning 0 means that we don't want to pass ourselves up to the message layer !!!
189 my( $self, $session, $mtype, $api_level, $tT ) = @_;
191 # A Server should never receive STATUS messages. If so, we drop them.
192 # This is to keep STATUS's from dead client sessions from creating new server
193 # sessions which send mangled session exceptions to backends for messages
194 # that they are not aware of any more.
195 if( $mtype eq 'STATUS' ) { return 0; }
198 if ($mtype eq 'DISCONNECT') {
199 $session->disconnect;
204 if ($session->state == $session->CONNECTING()) {
206 if($mtype ne "CONNECT" and $session->stateless) {
207 $log->debug("Got message Stateless", DEBUG);
208 return 1; #pass the message up the stack
211 # the transport layer thinks this is a new connection. is it?
212 unless ($mtype eq 'CONNECT') {
213 $log->error("Connection seems to be mangled: Got $mtype instead of CONNECT");
215 my $res = OpenSRF::DomainObject::oilsBrokenSession->new(
216 status => "Connection seems to be mangled: Got $mtype instead of CONNECT",
219 $session->status($res);
225 my $res = OpenSRF::DomainObject::oilsConnectStatus->new;
226 $session->status($res);
227 $session->state( $session->CONNECTED );
233 $log->debug("Passing to Application::handler()", INFO);
234 $log->debug($self->toString(1), DEBUG);
241 # Handle client side message processing. Return 1 when the the message should be pushed
242 # up to the application layer. return 0 otherwise.
245 my( $self, $session , $mtype, $api_level, $tT) = @_;
248 if ($mtype eq 'STATUS') {
250 if ($self->payload->statusCode == STATUS_OK) {
251 $session->state($session->CONNECTED);
252 $log->debug("We connected successfully to ".$session->app, INFO);
256 if ($self->payload->statusCode == STATUS_TIMEOUT) {
257 $session->state( $session->DISCONNECTED );
259 $session->push_resend( $session->app_request($self->threadTrace) );
260 $log->debug("Disconnected because of timeout", WARN);
263 } elsif ($self->payload->statusCode == STATUS_REDIRECTED) {
264 $session->state( $session->DISCONNECTED );
266 $session->push_resend( $session->app_request($self->threadTrace) );
267 $log->debug("Disconnected because of redirect", WARN);
270 } elsif ($self->payload->statusCode == STATUS_EXPFAILED) {
271 $session->state( $session->DISCONNECTED );
272 $log->debug("Disconnected because of mangled session", WARN);
274 $session->push_resend( $session->app_request($self->threadTrace) );
277 } elsif ($self->payload->statusCode == STATUS_CONTINUE) {
280 } elsif ($self->payload->statusCode == STATUS_COMPLETE) {
281 my $req = $session->app_request($self->threadTrace);
282 $req->complete(1) if ($req);
286 # add more STATUS handling code here (as 'elsif's), for Message layer status stuff
288 } elsif ($session->state == $session->CONNECTING()) {
289 # This should be changed to check the type of response (is it a connectException?, etc.)
292 if( $self->payload and $self->payload->class->isa( "OpenSRF::EX" ) ) {
293 $self->payload->throw();
296 if( $self->payload ) {
297 $log->debug("Passing to OpenSRF::Application::handler()\n" . $self->payload->toString(1), INTERNAL);
299 $log->debug("oilsMessage passing to Application: " . $self->type." : ".$session->remote_id, INFO );