source: trunk/athena/bin/discuss/usp/block.c @ 438

Revision 438, 5.3 KB checked in by spook, 37 years ago (diff)
Fixed for saber.
Line 
1/* UNIX Unified Stream Protocol
2
3   Copyright 1986 by the Massachusetts Institute of Technology
4   See permission and disclaimer notice in file "notice.h"
5*/
6
7#include <sys/types.h>
8#include <stdio.h>
9#include <strings.h>
10#include "gen.h"
11#include "usp.h"
12#include <netinet/in.h>
13
14char *error_message();
15/* USP block operations */
16
17int usp_internal_errno = 0;
18char usp_internal_string[256];
19
20char *usp_setup_errlist[] = {
21    "foreign name unknown",
22    "service identifier unknown",
23    "host down",
24    "service not supported on host",
25    "service not currently available",
26    "protocol conversion not available"};
27
28char *usp_during_errlist[] = {
29    "transport failure",
30    "transport timeout",
31    "foreign client failure",
32    "path transformation impossible"};
33
34USP_rcv_blk(us, bt)
35
36USPStream   *us;
37USPCardinal *bt;
38{
39    errno = 0;
40
41    /* get block type */
42   
43    if(get_from_net(us, (char *) bt, sizeof(USPCardinal)) == ERROR) {
44        return(ERROR);
45    }
46    *bt = ntohs(*bt);
47    us->us_in_receiving_p = TRUE;
48    us->us_nunread_sub_block_bytes = 0;
49    if(get_sub_block_header(us) == ERROR) {
50        return(ERROR);
51    }
52
53    /* sneak a look at the block type.  If CONNECTION-ERROR,
54       intercept it, parse the reason and return an error to
55       the client */
56
57    if(*bt == CONNECTION_ERROR) {
58        USPCardinal what_error, who_reported;
59        USPString   info, module_name;
60        char        what_string[256], who_string[65];
61       
62        errno = UEINTERNAL;
63        if(USP_get_cardinal(us, &what_error) == ERROR) {
64            USP_flush_block(us);
65            strcpy(usp_internal_string, "CONNECTION-ERROR block read error");
66            return(ERROR);
67        }
68        switch(what_error) {
69          case CE_UNKNOWN:
70            strcpy(what_string, "unknown internal error");
71            break;
72          case CE_NAME_UNKNOWN:
73          case CE_SERVICE_UNKNOWN:
74          case CE_HOST_DOWN:
75          case CE_SERVICE_UNSUPPORTED:
76          case CE_SERVICE_UNAVAILABLE:
77          case CE_CONVERSION_UNAVAILABLE:
78            strcpy(what_string, usp_setup_errlist[what_error - CE_NAME_UNKNOWN]);
79            break;
80          case CE_TRANSPORT_FAILURE:
81          case CE_TRANSPORT_TIMEOUT:
82          case CE_CLIENT_FAILURE:
83          case CE_PATH_TRANSLATION:
84            strcpy(what_string, usp_during_errlist[what_error - CE_TRANSPORT_FAILURE]);
85            break;
86          default:
87            sprintf(what_string, "(unknown internal error code %u)", what_error);
88            break;
89        }
90        if(USP_get_string(us, &info) == ERROR) {
91            USP_flush_block(us);
92            strcpy(usp_internal_string, "CONNECTION-ERROR block read error");
93            return(ERROR);
94        }
95        if(USP_get_cardinal(us, &who_reported) == ERROR) {
96            USP_flush_block(us);
97            strcpy(usp_internal_string, "CONNECTION-ERROR block read error");
98            return(ERROR);
99        }
100        switch(who_reported) {
101          case FOREIGN_DETECT:
102            strcpy(who_string, "foreign client");
103            break;
104          case TRANSPORT_DETECT:
105            strcpy(who_string, "transport layer");
106            break;
107          case INTERMEDIATE_DETECT:
108            strcpy(who_string, "protocol converter");
109            break;
110          default:
111            strcpy(who_string, "[unknown]");
112        }
113        if(USP_get_string(us, &module_name) == ERROR) {
114            USP_flush_block(us);
115            strcpy(usp_internal_string, "CONNECTION-ERROR block read error");
116            return(ERROR);
117        }
118        sprintf(usp_internal_string, "Internal error \"%s\" (%s), detected by %s \"%s\"",
119                what_string, info, who_string, module_name);
120        cfree((char *) info);
121        cfree((char *) module_name);
122        return(ERROR);
123    }
124
125    /* if other end wishes to shut down, fine... */
126
127    else if(*bt == CONNECTION_END) {
128        if(USP_begin_block(us, CONNECTION_END_REPLY))
129          ;
130        if(USP_end_block(us) == ERROR)
131          ;
132        return(CLOSED);
133    }
134
135    /* if other end is sending an OPEN block, ignore it and get the next
136       block.  Note that we might recurse indefinitely if the other end
137       never sends anything but CONNECTION-OPEN blocks... */
138
139    else if(*bt == CONNECTION_OPEN) {
140        USP_flush_block(us);
141        return(USP_rcv_blk(us, bt));
142    }
143    return(SUCCESS);
144}
145
146USP_begin_block(us, bt)
147
148USPStream   *us;
149USPCardinal bt;
150{
151    errno = 0;
152    if(us->us_out_sending_p) {          /* already sending a block! */
153        errno = UECBNOTENDED;
154        return(ERROR);
155    }
156    bt = htons(bt);
157    if(put_onto_net(us, (char *) &bt, sizeof(USPCardinal), FALSE) == ERROR) {
158        return(ERROR);
159    }
160    us->us_out_sending_p = TRUE;
161    us->us_nsent_sub_block_bytes = 0;                                   
162    return(SUCCESS);
163}
164
165/* end block and flush buffer */
166
167USP_end_block(us)
168
169USPStream    *us;
170{
171    errno = 0;
172    if(! us->us_out_sending_p) {
173        errno = UENOTSENDING;
174        return(ERROR);
175    }
176    if(send_sub_block(us, TRUE) == ERROR) { /* force send of last sub-block */
177        return(ERROR);
178    }
179    us->us_out_sending_p = FALSE;
180    return(SUCCESS);
181}
182
183/* skip to end of block (does nothing if already there) */
184
185USP_flush_block(us)
186
187USPStream    *us;
188{
189    errno = 0;
190    if(! us->us_in_receiving_p) {               /* already there? */
191        return;
192    }
193    while(! us->us_last_sub_block_p) {         
194        if(skip_sub_block(us) == ERROR) {
195            return;
196        }
197        if(get_sub_block_header(us) == ERROR) {
198            return;
199        }
200    }
201
202    /* and skip over the last sub-block */
203
204    if(skip_sub_block(us) == ERROR) {
205        return;
206    }
207    us->us_in_receiving_p = FALSE;
208}
209
210
211Boolean USP_end_of_block_p(us)
212
213USPStream       *us;
214{
215    return(((us->us_nunread_sub_block_bytes == 0) && us->us_last_sub_block_p) ?
216           TRUE : FALSE);
217}
218
219
220
221char *usp_error(errnum)
222
223int errnum;
224{
225    if(errnum == UEINTERNAL) {
226        return(usp_internal_string);
227    }
228    else {
229        return(error_message(errnum));
230    }
231}
Note: See TracBrowser for help on using the repository browser.