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