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

Revision 23149, 6.9 KB checked in by andersk, 16 years ago (diff)
In discuss: * Fix some trivial typos.
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/*
85 * $Id: main.c,v 1.8 1999-02-02 20:40:48 kcr Exp $
86 */
87
88#include <stdio.h>
89#include <errno.h>
90#include <string.h>
91#include <sys/types.h>
92#include <sys/socket.h>
93#include <netdb.h>
94#include <netinet/in.h>
95#include "gen.h"
96#include "usp.h"
97
98static char rcsid[] =
99    "$Id: main.c,v 1.8 1999-02-02 20:40:48 kcr Exp $";
100
101/* connection operations */
102
103/* make a USP connection to a given server */
104
105USPStream *USP_make_connection(host, service)
106
107char    *host;
108char    *service;
109{
110     struct sockaddr_in address;
111     struct servent     *svc_info;
112     struct hostent     *host_info;
113     int                s, melen = 64;
114     char               me[65];
115     USPStream          *us;
116
117     errno = 0;
118     if(! (svc_info = getservbyname(service, "tcp"))) {
119         return(NULL);
120     }
121     if(! (host_info = gethostbyname(host))) {
122         return(NULL);
123     }
124     memset(&address, 0, sizeof(address));
125     memcpy(&address.sin_addr, host_info->h_addr, host_info->h_length);
126     address.sin_family = host_info->h_addrtype;
127     address.sin_port = svc_info->s_port;
128     if((s = socket(host_info->h_addrtype, SOCK_STREAM, 0)) == ERROR) {
129         return(NULL);
130     }
131     if(connect(s, (struct sockaddr *) &address, sizeof(address)) == ERROR) {
132         return(NULL);
133     }
134     if((us = USP_associate(s))) {
135
136         /* set up and transmit "connection-open" block */
137
138         if(USP_begin_block(us, CONNECTION_OPEN) == ERROR) {
139             USP_shutdown(us);
140             return(NULL);
141         }
142         if(USP_put_cardinal(us, GLOBAL_NAME) == ERROR) {
143             USP_shutdown(us);
144             return(NULL);
145         }
146         if(USP_put_string(us, host_info->h_name) == ERROR) {
147             USP_shutdown(us);
148             return(NULL);
149         }
150         if(USP_put_cardinal(us, GLOBAL_NAME) == ERROR) {
151             USP_shutdown(us);
152             return(NULL);
153         }       
154         if(gethostname(me, melen) == ERROR) {
155             USP_shutdown(us);
156             return(NULL);
157         }       
158         if(USP_put_string(us, me) == ERROR) {
159             USP_shutdown(us);
160             return(NULL);
161         }
162         if(USP_put_string(us, svc_info->s_name) == ERROR) {
163             USP_shutdown(us);
164             return(NULL);
165         }
166         if(USP_end_block(us) == ERROR) {
167             USP_shutdown(us);
168             return(NULL);
169         }
170     }
171     return(us);
172}
173
174/* associate a USP connection with an already open socket */
175
176USPStream *USP_associate(s)
177
178int     s;
179{
180     USPStream  *us;
181     int        write_desc;
182     int        on = 1;
183
184     /* set up unified stream */
185     
186     if(! (us = (USPStream *) calloc(1, sizeof(USPStream)))) {
187          return(NULL);
188     }
189     /* (don't care much if this fails) */
190     (void) setsockopt (s, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
191#if 0
192     write_desc = dup(s);
193#else
194     write_desc = s;
195#endif
196     if(write_desc == ERROR) {
197         free((char *) us);
198         return(NULL);
199     }
200     if(! (us->us_read = fdopen(s, "r"))) {
201         free((char *) us);
202         return(NULL);
203     }
204     if(! (us->us_write = fdopen(write_desc, "w"))) {
205         free((char *) us);
206         return(NULL);
207     }
208     us->us_in_receiving_p = FALSE;
209     us->us_out_sending_p = FALSE;
210     return(us);
211}
212
213/* initiate the close of a unified stream connection */
214
215USP_close_connection(us)
216
217USPStream          *us;
218{
219    int status = SUCCESS;
220    USPCardinal bt;
221
222    errno = 0;
223
224    /* start USP close sequence */
225
226
227    if(USP_begin_block(us, CONNECTION_END) == ERROR) {
228        status = ERROR;
229    }
230    if(USP_end_block(us) == ERROR) {
231        status = ERROR;
232    }
233   
234    /* wait for CONNECTION-END-REPLY block */
235
236    if(USP_rcv_blk(us, &bt) == ERROR) {
237        status = ERROR;
238    }
239    else if(bt != CONNECTION_END_REPLY) {
240        status = ERROR;
241    }
242    else if(USP_begin_block(us, CONNECTION_END_REPLY) == ERROR) {
243        status = ERROR;
244    }
245    else if(USP_end_block(us) == ERROR) {
246        status = ERROR;
247    }
248    status = USP_shutdown(us);
249    return(status);
250}
251
252USP_shutdown(us)
253
254USPStream *us;
255{
256    int status = SUCCESS;
257
258    if(fclose(us->us_read) == EOF) {
259        status = ERROR;
260    }
261    if(fclose(us->us_write) == EOF) {
262        status = ERROR;
263    }
264    free((char *) us);
265    return(status);
266}
Note: See TracBrowser for help on using the repository browser.