~ubuntu-branches/ubuntu/precise/netatalk/precise

« back to all changes in this revision

Viewing changes to etc/papd/session.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Rittau
  • Date: 2004-01-19 12:43:49 UTC
  • Revision ID: james.westby@ubuntu.com-20040119124349-es563jbp0hk0ae51
Tags: upstream-1.6.4
ImportĀ upstreamĀ versionĀ 1.6.4

Show diffs side-by-side

added added

removed removed

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