source: trunk/athena/bin/discuss/usp/main.c @ 1823

Revision 1823, 6.7 KB checked in by raeburn, 35 years ago (diff)
Initial revision
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   First implementation, long ago in a galaxy far far away: Ted Kim
7   Many bug fixes: Mark L. Lambert
8   
9   7/1/86 SRZ: added USP_make_connection and USP_associate calls. 
10               USP_accept_connection now calls USP_associate.
11
12   7/7/86 MLL: USP_accept_connection now takes fork flag and does not fork if
13               flag value is FALSE.  This is for running USP applications under
14               dbx. 
15               Each interface operation now clears errno before beginning
16
17   7/8/86 SRZ: Get_from_net bug fixed--a 0 return from recv used to cause an
18               infinite loop if the other end disappeared suddenly.  Now
19               errno is set to ECONNRESET and ERROR is returned...
20
21   7/9/86 MLL: Cleaned up last of TK brain damage (I think) and fixed a bug
22               in put_onto_net that caused it to return random garbage instead
23               of SUCCESS/ERROR. 
24               Punted USP_accept_connection
25               Punted select/send/recv calls in favor of simple read and write
26               calls
27               Get_from_net does not return ERROR/ECONNRESET on 0 byte read
28               return (turns out read call is allowed to return 0 bytes if no
29               data happens to be available at the moment). 
30
31   7/10/86 MLL: replaced single read/write socket in USPStream structure with
32                a pair of FILE stream pointers, created via fdopen after a
33                DUP call.  This allows buffered data sends with (presumably)
34                fewer packet transmissions.  Replaced read/write with fread/
35                fwrite
36                Added USP_put/get_byte_block calls to get at raw USP block
37               
38   8/26/86 MLL: Implemented open-connection, connection-error, end, and
39                end-reply blocks as per the USP spec.  Yuk.
40
41
42   This library contains the following calls:
43
44   Connection operations (main.c)
45
46   (USPStream *) USP_make_connection((char *), (char *))
47   (USPStream *) USP_associate((int))
48   USP_close_connection(USPStream *))
49
50   Block operations (block.c)
51
52   USP_rcv_blk((USPStream *), (USPCardinal *))
53   USP_begin_block((USPStream *), (USPCardinal))
54   USP_end_block((USPStream *))
55   USP_flush_block((USPStream *))
56   Boolean USP_end_of_block_p((USPStream *))
57
58   Input operations (get.c)
59
60   USP_get_boolean((USPStream *), (USPBoolean *))
61   USP_get_integer((USPStream *), (USPInteger *))
62   USP_get_cardinal((USPStream *), (USPCardinal *))
63   USP_get_long_integer((USPStream *), (USPLong_integer *))
64   USP_get_long_cardinal((USPStream *), (USPLong_cardinal *))
65   USP_get_string((USPStream *), (USPString *))
66   USP_get_byte_block((USPStream *), (Byte *), (unsigned), (unsigned *))
67
68   Output operations (put.c)
69
70   USP_put_boolean((USPStream *), (USPBoolean))
71   USP_put_integer((USPStream *), (USPInteger))
72   USP_put_cardinal((USPStream *), (USPCardinal))
73   USP_put_long_integer((USPStream *), (USPLong_integer))
74   USP_put_long_cardinal((USPStream *), (USPLong_cardinal))
75   USP_put_string((USPStream *), (USPString))
76   USP_put_byte_block((USPStream *), (Byte *), (unsigned))
77
78   Miscellaneous operations (block.c)
79
80   (char *) usp_error((int))
81
82*/
83
84#include <stdio.h>
85#include <errno.h>
86#include <strings.h>
87#include <sys/types.h>
88#include <sys/socket.h>
89#include <netdb.h>
90#include <netinet/in.h>
91#include "gen.h"
92#include "usp.h"
93
94/* connection operations */
95
96/* make a USP connection to a given server */
97
98USPStream *USP_make_connection(host, service)
99
100char    *host;
101char    *service;
102{
103     struct sockaddr_in address;
104     struct servent     *svc_info;
105     struct hostent     *host_info;
106     int                s, melen = 64;
107     char               me[65];
108     USPStream          *us;
109
110     errno = 0;
111     if(! (svc_info = getservbyname(service, "tcp"))) {
112         return(NULL);
113     }
114     if(! (host_info = gethostbyname(host))) {
115         return(NULL);
116     }
117     bzero((char *) &address, sizeof(address));
118     bcopy(host_info->h_addr, (char *) &address.sin_addr, host_info->h_length);
119     address.sin_family = host_info->h_addrtype;
120     address.sin_port = svc_info->s_port;
121     if((s = socket(host_info->h_addrtype, SOCK_STREAM, 0)) == ERROR) {
122         return(NULL);
123     }
124     if(connect(s, (char *) &address, sizeof(address)) == ERROR) {
125         return(NULL);
126     }
127     if((us = USP_associate(s))) {
128
129         /* set up and transmit "connection-open" block */
130
131         if(USP_begin_block(us, CONNECTION_OPEN) == ERROR) {
132             USP_shutdown(us);
133             return(NULL);
134         }
135         if(USP_put_cardinal(us, GLOBAL_NAME) == ERROR) {
136             USP_shutdown(us);
137             return(NULL);
138         }
139         if(USP_put_string(us, host_info->h_name) == ERROR) {
140             USP_shutdown(us);
141             return(NULL);
142         }
143         if(USP_put_cardinal(us, GLOBAL_NAME) == ERROR) {
144             USP_shutdown(us);
145             return(NULL);
146         }       
147         if(gethostname(me, &melen) == ERROR) {
148             USP_shutdown(us);
149             return(NULL);
150         }       
151         if(USP_put_string(us, me) == ERROR) {
152             USP_shutdown(us);
153             return(NULL);
154         }
155         if(USP_put_string(us, svc_info->s_name) == ERROR) {
156             USP_shutdown(us);
157             return(NULL);
158         }
159         if(USP_end_block(us) == ERROR) {
160             USP_shutdown(us);
161             return(NULL);
162         }
163     }
164     return(us);
165}
166
167/* associate a USP connection with an already open socket */
168
169USPStream *USP_associate(s)
170
171int     s;
172{
173     USPStream  *us;
174     int        write_desc;
175     int        on = 1;
176
177     /* set up unified stream */
178     
179     if(! (us = (USPStream *) calloc(1, sizeof(USPStream)))) {
180          return(NULL);
181     }
182     /* (don't care much if this fails) */
183     (void) setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
184     if((write_desc = dup(s)) == ERROR) {
185         cfree((char *) us);
186         return(NULL);
187     }
188     if(! (us->us_read = fdopen(s, "r"))) {
189         cfree((char *) us);
190         return(NULL);
191     }
192     if(! (us->us_write = fdopen(write_desc, "w"))) {
193         cfree((char *) us);
194         return(NULL);
195     }
196     us->us_in_receiving_p = FALSE;
197     us->us_out_sending_p = FALSE;
198     return(us);
199}
200
201/* initiate the close of a unified stream connection */
202
203USP_close_connection(us)
204
205USPStream          *us;
206{
207    int status = SUCCESS;
208    USPCardinal bt;
209
210    errno = 0;
211
212    /* start USP close sequence */
213
214
215    if(USP_begin_block(us, CONNECTION_END) == ERROR) {
216        status = ERROR;
217    }
218    if(USP_end_block(us) == ERROR) {
219        status = ERROR;
220    }
221   
222    /* wait for CONNECTION-END-REPLY block */
223
224    if(USP_rcv_blk(us, &bt) == ERROR) {
225        status = ERROR;
226    }
227    else if(bt != CONNECTION_END_REPLY) {
228        status = ERROR;
229    }
230    else if(USP_begin_block(us, CONNECTION_END_REPLY) == ERROR) {
231        status = ERROR;
232    }
233    else if(USP_end_block(us) == ERROR) {
234        status = ERROR;
235    }
236    status = USP_shutdown(us);
237    return(status);
238}
239
240USP_shutdown(us)
241
242USPStream *us;
243{
244    int status = SUCCESS;
245
246    if(fclose(us->us_read) == EOF) {
247        status = ERROR;
248    }
249    if(fclose(us->us_write) == EOF) {
250        status = ERROR;
251    }
252    cfree((char *) us);
253    return(status);
254}
Note: See TracBrowser for help on using the repository browser.