1 package OpenSRF::DomainObject::oilsMessage;
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/;
9 JSON->register_class_hint(hint => 'osrfMessage', class => 'OpenSRF::DomainObject::oilsMessage');
14 return JSON->perl2prettyJSON($self) if ($pretty);
15 return JSON->perl2JSON($self);
21 OpenSRF::DomainObject::oilsMessage
25 use OpenSRF::DomainObject::oilsMessage;
27 my $msg = OpenSRF::DomainObject::oilsMessage->new( type => 'CONNECT' );
29 $msg->payload( $domain_object );
33 OpenSRF::DomainObject::oilsMessage is used internally to wrap data sent
34 between client and server. It provides the structure needed to authenticate
35 session data, and also provides the logic needed to unwrap session data and
36 pass this information along to the Application Layer.
40 my $log = 'OpenSRF::Utils::Logger';
44 =head2 OpenSRF::DomainObject::oilsMessage->type( [$new_type] )
48 Used to specify the type of message. One of
49 B<CONNECT, REQUEST, RESULT, STATUS, ERROR, or DISCONNECT>.
58 $self->{type} = $val if (defined $val);
62 =head2 OpenSRF::DomainObject::oilsMessage->api_level( [$new_api_level] )
66 Used to specify the api_level of message. Currently, only api_level C<1> is
67 supported. This will be used to check that messages are well-formed, and as
68 a hint to the Application as to which version of a method should fulfill a
78 $self->{api_level} = $val if (defined $val);
79 return $self->{api_level};
82 =head2 OpenSRF::DomainObject::oilsMessage->threadTrace( [$new_threadTrace] );
86 Sets or gets the current message sequence identifier, or thread trace number,
87 for a message. Useful as a debugging aid, but that's about it.
96 $self->{threadTrace} = $val if (defined $val);
97 return $self->{threadTrace};
100 =head2 OpenSRF::DomainObject::oilsMessage->update_threadTrace
104 Increments the threadTrace component of a message. This is automatic when
105 using the normal session processing stack.
111 sub update_threadTrace {
113 my $tT = $self->threadTrace;
118 $log->debug("Setting threadTrace to $tT",DEBUG);
120 $self->threadTrace($tT);
125 =head2 OpenSRF::DomainObject::oilsMessage->payload( [$new_payload] )
129 Sets or gets the payload of a message. This should be exactly one object
130 of (sub)type domainObject or domainObjectCollection.
139 $self->{payload} = $val if (defined $val);
140 return $self->{payload};
143 =head2 OpenSRF::DomainObject::oilsMessage->handler( $session_id )
147 Used by the message processing stack to set session state information from the current
148 message, and then sends control (via the payload) to the Application layer.
158 my $mtype = $self->type;
159 my $api_level = $self->api_level || 1;;
160 my $tT = $self->threadTrace;
162 $session->last_message_type($mtype);
163 $session->last_message_api_level($api_level);
164 $session->last_threadTrace($tT);
166 $log->debug(" Received api_level => [$api_level], MType => [$mtype], ".
167 "from [".$session->remote_id."], threadTrace[".$self->threadTrace."]", INFO);
168 $log->debug("endpoint => [".$session->endpoint."]", DEBUG);
169 $log->debug("OpenSRF::AppSession->SERVER => [".$session->SERVER()."]", DEBUG);
173 if ( $session->endpoint == $session->SERVER() ) {
174 $val = $self->do_server( $session, $mtype, $api_level, $tT );
176 } elsif ($session->endpoint == $session->CLIENT()) {
177 $val = $self->do_client( $session, $mtype, $api_level, $tT );
181 $log->debug("Passing request up to OpenSRF::Application", DEBUG);
182 return OpenSRF::Application->handler($session, $self->payload);
184 $log->debug("Request was handled internally", DEBUG);
193 # handle server side message processing
195 # !!! Returning 0 means that we don't want to pass ourselves up to the message layer !!!
197 my( $self, $session, $mtype, $api_level, $tT ) = @_;
199 # A Server should never receive STATUS messages. If so, we drop them.
200 # This is to keep STATUS's from dead client sessions from creating new server
201 # sessions which send mangled session exceptions to backends for messages
202 # that they are not aware of any more.
203 if( $mtype eq 'STATUS' ) { return 0; }
206 if ($mtype eq 'DISCONNECT') {
207 $session->disconnect;
212 if ($session->state == $session->CONNECTING()) {
214 if($mtype ne "CONNECT" and $session->stateless) {
215 $log->debug("Got message Stateless", DEBUG);
216 return 1; #pass the message up the stack
219 # the transport layer thinks this is a new connection. is it?
220 unless ($mtype eq 'CONNECT') {
221 $log->error("Connection seems to be mangled: Got $mtype instead of CONNECT");
223 my $res = OpenSRF::DomainObject::oilsBrokenSession->new(
224 status => "Connection seems to be mangled: Got $mtype instead of CONNECT",
227 $session->status($res);
233 my $res = OpenSRF::DomainObject::oilsConnectStatus->new;
234 $session->status($res);
235 $session->state( $session->CONNECTED );
241 $log->debug("Passing to Application::handler()", INFO);
242 $log->debug($self->toString(1), DEBUG);
249 # Handle client side message processing. Return 1 when the the message should be pushed
250 # up to the application layer. return 0 otherwise.
253 my( $self, $session , $mtype, $api_level, $tT) = @_;
256 if ($mtype eq 'STATUS') {
258 if ($self->payload->statusCode == STATUS_OK) {
259 $session->state($session->CONNECTED);
260 $log->debug("We connected successfully to ".$session->app, INFO);
264 if ($self->payload->statusCode == STATUS_TIMEOUT) {
265 $session->state( $session->DISCONNECTED );
268 $session->push_resend( $session->app_request($self->threadTrace) );
269 $log->debug("Disconnected because of timeout", WARN);
272 } elsif ($self->payload->statusCode == STATUS_REDIRECTED) {
273 $session->state( $session->DISCONNECTED );
276 $session->push_resend( $session->app_request($self->threadTrace) );
277 $log->debug("Disconnected because of redirect", WARN);
280 } elsif ($self->payload->statusCode == STATUS_EXPFAILED) {
281 $session->state( $session->DISCONNECTED );
282 $log->debug("Disconnected because of mangled session", WARN);
284 $session->push_resend( $session->app_request($self->threadTrace) );
287 } elsif ($self->payload->statusCode == STATUS_CONTINUE) {
288 $session->reset_request_timeout($self->threadTrace);
291 } elsif ($self->payload->statusCode == STATUS_COMPLETE) {
292 my $req = $session->app_request($self->threadTrace);
293 $req->complete(1) if ($req);
297 # add more STATUS handling code here (as 'elsif's), for Message layer status stuff
299 } elsif ($session->state == $session->CONNECTING()) {
300 # This should be changed to check the type of response (is it a connectException?, etc.)
303 if( $self->payload and $self->payload->isa( "OpenSRF::EX" ) ) {
304 $self->payload->throw();
307 if( $self->payload ) {
308 $log->debug("Passing to OpenSRF::Application::handler()\n" . $self->payload->toString(1), INTERNAL);
310 $log->debug("oilsMessage passing to Application: " . $self->type." : ".$session->remote_id, INFO );