]> arthur.barton.de Git - netatalk.git/blob - etc/papd/session.c
prototyping to allow the compiler to do some real argument checking
[netatalk.git] / etc / papd / session.c
1 /*
2  * Copyright (c) 1990,1994 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5
6 #ifdef HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/syslog.h>
14 #include <sys/time.h>
15 #include <sys/uio.h>
16 #include <netatalk/endian.h>
17 #include <netatalk/at.h>
18 #include <atalk/atp.h>
19 #include <atalk/pap.h>
20
21 #include "file.h"
22 #include "lp.h"
23 #include "session.h"
24
25 extern unsigned char    connid, quantum, oquantum;
26
27 char            buf[ PAP_MAXQUANTUM ][ 4 + PAP_MAXDATA ];
28 struct iovec    niov[ PAP_MAXQUANTUM ] = {
29     { buf[ 0 ], 0 },
30     { buf[ 1 ], 0 },
31     { buf[ 2 ], 0 },
32     { buf[ 3 ], 0 },
33     { buf[ 4 ], 0 },
34     { buf[ 5 ], 0 },
35     { buf[ 6 ], 0 },
36     { buf[ 7 ], 0 },
37 };
38 struct iovec    iov[ PAP_MAXQUANTUM ] = {
39     { buf[ 0 ] + 4,     0 },
40     { buf[ 1 ] + 4,     0 },
41     { buf[ 2 ] + 4,     0 },
42     { buf[ 3 ] + 4,     0 },
43     { buf[ 4 ] + 4,     0 },
44     { buf[ 5 ] + 4,     0 },
45     { buf[ 6 ] + 4,     0 },
46     { buf[ 7 ] + 4,     0 },
47 };
48
49 /*
50  * Accept files until the client closes the connection.
51  * Read lines of a file, until the client sends eof, after
52  * which we'll send eof also.
53  */
54 int session( atp, sat )
55     ATP                 atp;
56     struct sockaddr_at  *sat;
57 {
58     struct timeval      tv;
59     struct atp_block    atpb;
60     struct sockaddr_at  ssat;
61     struct papfile      infile, outfile;
62     fd_set              fds;
63     char                cbuf[ 578 ];
64     int                 i, cc, timeout = 0, readpending = 0;
65     u_int16_t           seq = 0, rseq = 1, netseq;
66     u_char              readport;
67
68     infile.pf_state = PF_BOT;
69     infile.pf_bufsize = 0;
70     infile.pf_datalen = 0;
71     infile.pf_buf = 0;
72     infile.pf_data = 0;
73
74     outfile.pf_state = PF_BOT;
75     outfile.pf_bufsize = 0;
76     outfile.pf_datalen = 0;
77     outfile.pf_buf = 0;
78     outfile.pf_data = 0;
79
80     /*
81      * Ask for data.
82      */
83     cbuf[ 0 ] = connid;
84     cbuf[ 1 ] = PAP_READ;
85     if (++seq == 0) seq = 1;
86     netseq = htons( seq );
87     bcopy( &netseq, &cbuf[ 2 ], sizeof( netseq ));
88     atpb.atp_saddr = sat;
89     atpb.atp_sreqdata = cbuf;
90     atpb.atp_sreqdlen = 4;              /* bytes in SendData request */
91     atpb.atp_sreqto = 5;                /* retry timer */
92     atpb.atp_sreqtries = -1;            /* infinite retries */
93     if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
94         syslog( LOG_ERR, "atp_sreq: %m" );
95         return( -1 );
96     }
97
98     for (;;) {
99         /*
100          * Time between tickles.
101          */
102         tv.tv_sec = 60;
103         tv.tv_usec = 0;
104
105         /*
106          * If we don't get anything for a while, time out.
107          */
108         FD_ZERO( &fds );
109         FD_SET( atp_fileno( atp ), &fds );
110
111         if (( cc = select( FD_SETSIZE, &fds, 0, 0, &tv )) < 0 ) {
112             syslog( LOG_ERR, "select: %m" );
113             return( -1 );
114         }
115         if ( cc == 0 ) {
116             if ( timeout++ > 2 ) {
117                 syslog( LOG_ERR, "connection timed out" );
118                 lp_cancel();
119                 return( -1 );
120             }
121
122             /*
123              * Send a tickle.
124              */
125             cbuf[ 0 ] = connid;
126             cbuf[ 1 ] = PAP_TICKLE;
127             cbuf[ 2 ] = cbuf[ 3 ] = 0;
128             atpb.atp_saddr = sat;
129             atpb.atp_sreqdata = cbuf;
130             atpb.atp_sreqdlen = 4;              /* bytes in Tickle request */
131             atpb.atp_sreqto = 0;                /* best effort */
132             atpb.atp_sreqtries = 1;             /* try once */
133             if ( atp_sreq( atp, &atpb, 0, 0 )) {
134                 syslog( LOG_ERR, "atp_sreq: %m" );
135                 return( -1 );
136             }
137             continue;
138         } else {
139             timeout = 0;
140         }
141
142         memset( &ssat, 0, sizeof( struct sockaddr_at ));
143         switch( atp_rsel( atp, &ssat, ATP_TRESP | ATP_TREQ )) {
144         case ATP_TREQ :
145             atpb.atp_saddr = &ssat;
146             atpb.atp_rreqdata = cbuf;
147             atpb.atp_rreqdlen = sizeof( cbuf );
148             if ( atp_rreq( atp, &atpb ) < 0 ) {
149                 syslog( LOG_ERR, "atp_rreq: %m" );
150                 return( -1 );
151             }
152             /* sanity */
153             if ( (unsigned char)cbuf[ 0 ] != connid ) {
154                 syslog( LOG_ERR, "Bad ATP request!" );
155                 continue;
156             }
157
158             switch( cbuf[ 1 ] ) {
159             case PAP_READ :
160                 /*
161                  * Other side is ready for some data.
162                  */
163                 bcopy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
164                 if ( netseq != 0 ) {
165                     if ( rseq != ntohs( netseq )) {
166                         break;
167                     }
168                     if ( rseq++ == 0xffff ) rseq = 1;
169                 }
170                 readpending = 1;
171                 readport = ssat.sat_port;
172                 break;
173
174             case PAP_CLOSE :
175                 /*
176                  * Respond to the close request.
177                  * If we're in the middle of a file, clean up.
178                  */
179                 if (( infile.pf_state & PF_BOT ) ||
180                         ( infile.pf_datalen == 0 &&
181                         ( infile.pf_state & PF_EOF ))) {
182                     lp_print();
183                 } else {
184                     lp_cancel();
185                 }
186
187                 niov[ 0 ].iov_len = 4;
188                 ((char *)niov[ 0 ].iov_base)[ 0 ] = connid;
189                 ((char *)niov[ 0 ].iov_base)[ 1 ] = PAP_CLOSEREPLY;
190                 ((char *)niov[ 0 ].iov_base)[ 2 ] =
191                         ((char *)niov[ 0 ].iov_base)[ 3 ] = 0;
192                 atpb.atp_sresiov = niov;
193                 atpb.atp_sresiovcnt = 1;
194                 if ( atp_sresp( atp, &atpb ) < 0 ) {
195                     syslog( LOG_ERR, "atp_sresp: %m" );
196                     exit( 1 );
197                 }
198                 return( 0 );
199                 break;
200
201             case PAP_TICKLE :
202                 break;
203             default :
204                 syslog( LOG_ERR, "Bad PAP request!" );
205             }
206
207             break;
208
209         case ATP_TRESP :
210             atpb.atp_saddr = &ssat;
211             for ( i = 0; i < oquantum; i++ ) {
212                 niov[ i ].iov_len = PAP_MAXDATA + 4;
213             }
214             atpb.atp_rresiov = niov;
215             atpb.atp_rresiovcnt = oquantum;
216             if ( atp_rresp( atp, &atpb ) < 0 ) {
217                 syslog( LOG_ERR, "atp_rresp: %m" );
218                 return( -1 );
219             }
220
221             /* sanity */
222             if ( ((unsigned char *)niov[ 0 ].iov_base)[ 0 ] != connid ||
223                     ((char *)niov[ 0 ].iov_base)[ 1 ] != PAP_DATA ) {
224                 syslog( LOG_ERR, "Bad data response!" );
225                 continue;
226             }
227
228             for ( i = 0; i < atpb.atp_rresiovcnt; i++ ) {
229                 append( &infile,
230                         niov[ i ].iov_base + 4, niov[ i ].iov_len - 4 );
231                 if (( infile.pf_state & PF_EOF ) == 0 &&
232                         ((char *)niov[ 0 ].iov_base)[ 2 ] ) {
233                     infile.pf_state |= PF_EOF;
234                 }
235             }
236
237             /* move data */
238             if ( ps( &infile, &outfile, sat ) < 0 ) {
239                 syslog( LOG_ERR, "parse: bad return" );
240                 return( -1 );   /* really?  close? */
241             }
242
243             /*
244              * Ask for more data.
245              */
246             cbuf[ 0 ] = connid;
247             cbuf[ 1 ] = PAP_READ;
248             if ( ++seq == 0 ) seq = 1;
249             netseq = htons( seq );
250             memcpy( &cbuf[ 2 ], &netseq, sizeof( netseq ));
251             atpb.atp_saddr = sat;
252             atpb.atp_sreqdata = cbuf;
253             atpb.atp_sreqdlen = 4;              /* bytes in SendData request */
254             atpb.atp_sreqto = 5;                /* retry timer */
255             atpb.atp_sreqtries = -1;            /* infinite retries */
256             if ( atp_sreq( atp, &atpb, oquantum, ATP_XO )) {
257                 syslog( LOG_ERR, "atp_sreq: %m" );
258                 return( -1 );
259             }
260             break;
261
262         case 0:
263             break;
264
265         default :
266             syslog( LOG_ERR, "atp_rsel: %m" );
267             return( -1 );
268         }
269
270         /* send any data that we have */
271         if ( readpending &&
272                 ( outfile.pf_datalen || ( outfile.pf_state & PF_EOF ))) {
273             for ( i = 0; i < quantum; i++ ) {
274                 ((char *)niov[ i ].iov_base)[ 0 ] = connid;
275                 ((char *)niov[ i ].iov_base)[ 1 ] = PAP_DATA;
276                 ((char *)niov[ i ].iov_base)[ 2 ] =
277                         ((char *)niov[ i ].iov_base)[ 3 ] = 0;
278
279                 if ( outfile.pf_datalen > PAP_MAXDATA  ) {
280                     cc = PAP_MAXDATA;
281                 } else {
282                     cc = outfile.pf_datalen;
283                     if ( outfile.pf_state & PF_EOF ) {
284                         ((char *)niov[ 0 ].iov_base)[ 2 ] = 1;  /* eof */
285                         outfile.pf_state = PF_BOT;
286                         infile.pf_state = PF_BOT;
287                     }
288                 }
289
290                 niov[ i ].iov_len = 4 + cc;
291                 memcpy( niov[ i ].iov_base + 4, outfile.pf_data, cc );
292                 CONSUME( &outfile, cc );
293                 if ( outfile.pf_datalen == 0 ) {
294                     i++;
295                     break;
296                 }
297             }
298             ssat.sat_port = readport;
299             atpb.atp_saddr = &ssat;
300             atpb.atp_sresiov = niov;
301             atpb.atp_sresiovcnt = i;    /* reported by stevebn@pc1.eos.co.uk */
302             if ( atp_sresp( atp, &atpb ) < 0 ) {
303                 syslog( LOG_ERR, "atp_sresp: %m" );
304                 return( -1 );
305             }
306             readpending = 0;
307         }
308     }
309 }