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