4e83052d65f5eea376b3878976430922bf57fc15
[yaz-moved-to-github.git] / ziffy / apdu.c
1 /*
2  * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
3  * apdu.c - 
4  *
5  * Copyright (c) 1998-2001 R. Carbone <rocco@tecsiel.it> - Finsiel S.p.A.
6  * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22
23
24 /*
25  * Operating System include files
26  */
27 #include <stdio.h>
28
29 #include <time.h>
30 #if HAVE_SYS_TIME_H
31 #include <sys/time.h>
32 #endif
33
34 #include <sys/types.h>
35
36 #include "apdu.h"
37
38 /*
39  * The table of z3950 apdus
40  */
41 static z3950apdu apdutable [] =
42 {
43   { 20, "INIT request",      -1, NULL, NULL, 0, NULL, 0 },
44   { 21, "INIT response",     -1, NULL, NULL, 0, NULL, 0 },
45   { 22, "SEARCH request",    -1, NULL, NULL, 0, NULL, 0 },
46   { 23, "SEARCH response",   -1, NULL, NULL, 0, NULL, 0 },
47   { 24, "PRESENT request",   -1, NULL, NULL, 0, NULL, 0 },
48   { 25, "PRESENT response",  -1, NULL, NULL, 0, NULL, 0 },
49   { 26, "DELETE request",    -1, NULL, NULL, 0, NULL, 0 },
50   { 27, "DELETE response",   -1, NULL, NULL, 0, NULL, 0 },
51   { 28, "ACCESS request",    -1, NULL, NULL, 0, NULL, 0 },
52   { 29, "ACCESS response",   -1, NULL, NULL, 0, NULL, 0 },
53   { 30, "RESOURCE request",  -1, NULL, NULL, 0, NULL, 0 },
54   { 31, "RESOURCE response", -1, NULL, NULL, 0, NULL, 0 },
55   { 32, "TRIGGER request",   -1, NULL, NULL, 0, NULL, 0 },
56   { 33, "REPORT request",    -1, NULL, NULL, 0, NULL, 0 },
57   { 34, "REPORT response",   -1, NULL, NULL, 0, NULL, 0 },
58   { 35, "SCAN request",      -1, NULL, NULL, 0, NULL, 0 },
59   { 36, "SCAN response",     -1, NULL, NULL, 0, NULL, 0 },
60
61   { 43, "SORT request",      -1, NULL, NULL, 0, NULL, 0 },
62   { 44, "SORT response",     -1, NULL, NULL, 0, NULL, 0 },
63   { 45, "SEGMENT request",   -1, NULL, NULL, 0, NULL, 0 },
64   { 46, "EXTENDED request",  -1, NULL, NULL, 0, NULL, 0 },
65   { 47, "EXTENDED response", -1, NULL, NULL, 0, NULL, 0 },
66   { 48, "CLOSE request",     -1, NULL, NULL, 0, NULL, 0 },
67
68   { 0 },
69 };
70
71
72 z3950apdu * lookup (int tag)
73 {
74   z3950apdu * found = apdutable;
75
76   for (found = apdutable; found < apdutable +
77          (sizeof (apdutable) / sizeof (apdutable [0])); found ++)
78     if (found -> tag == tag)
79         break;
80
81   return (found);
82 }
83
84
85 static int bertag (u_char * apdu)
86 {
87   u_char * q = apdu;
88   int tag = * q & 0x1F;
89
90   if (tag > 30)
91     {
92       tag = 0;
93       q ++;
94       do
95         {
96           tag <<= 7;
97           tag |= * q & 0X7F;
98         }
99       while (* q ++ & 0X80);
100     }
101   return (tag);
102 }
103
104
105 /*
106  * An euristic Z39.50 event check routine that simply
107  * looks for the first tag in the APDU
108  */
109 z3950apdu * parseable (u_char * apdu, int len)
110 {
111   if (! len)
112     return (0);
113
114   return (lookup (bertag (apdu)));
115 }
116
117
118
119 struct timeval current_apdu = {0};
120 struct timeval first_apdu = {0};
121 struct timeval last_apdu = {0};
122
123 /*
124  * The time difference in milliseconds
125  */
126 time_t delta_time_in_milliseconds (const struct timeval * now,
127                                    const struct timeval * before)
128 {
129   /*
130    * compute delta in second, 1/10's and 1/1000's second units
131    */
132   time_t delta_seconds = now -> tv_sec - before -> tv_sec;
133   time_t delta_milliseconds = (now -> tv_usec - before -> tv_usec) / 1000;
134
135   if (delta_milliseconds < 0)
136     { /* manually carry a one from the seconds field */
137       delta_milliseconds += 1000;               /* 1e3 */
138       -- delta_seconds;
139     }
140   return ((delta_seconds * 1000) + delta_milliseconds);
141 }
142
143
144 /*
145  * return a well formatted timestamp
146  */
147 char * timestamp (const struct timeval * t, int fmt)
148 {
149   static char buf [16];
150
151   time_t now = time ((time_t *) 0);
152   struct tm * tm = localtime (& now);
153
154   gettimeofday (& current_apdu, NULL);
155
156   switch (fmt)
157     {
158     default:
159     case DELTA_FMT:
160       /*
161        * calculate the difference in milliseconds since the previous apdus was displayed
162        */
163       sprintf (buf, "%10ld ms", delta_time_in_milliseconds (& current_apdu, & last_apdu));
164       break;
165
166     case ABS_FMT:
167       sprintf (buf, "%02d:%02d:%02d.%06d",
168                tm -> tm_hour, tm -> tm_min, tm -> tm_sec, (int) t -> tv_usec);
169       break;
170
171     case RELATIVE_FMT:
172       /*
173        * calculate the difference in milliseconds since the previous apdus was displayed
174        */
175       sprintf (buf, "%10ld ms", delta_time_in_milliseconds (& current_apdu, & first_apdu));
176       break;
177     }
178
179   return (buf);
180 }