2 * $Id: atp_rsel.c,v 1.6 2009-10-14 01:38:28 didg Exp $
4 * Copyright (c) 1990,1997 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
10 #endif /* HAVE_CONFIG_H */
13 #include <sys/types.h>
19 #include <netatalk/endian.h>
20 #include <netatalk/at.h>
22 #include <atalk/netddp.h>
23 #include <atalk/compat.h>
24 #include <atalk/atp.h>
25 #include <atalk/util.h>
27 #include "atp_internals.h"
30 static int release_count = 0;
31 #endif /* DROP_ATPTREL */
35 resend_request(ATP ah)
38 * update bitmap and send request packet
40 struct atphdr req_hdr;
43 printf( "\n<%d> resend_request: resending %ld byte request packet",
44 getpid(), ah->atph_reqpkt->atpbuf_dlen );
45 atp_print_addr( " to", &ah->atph_reqpkt->atpbuf_addr );
47 bprint( ah->atph_reqpkt->atpbuf_info.atpbuf_data,
48 ah->atph_reqpkt->atpbuf_dlen );
51 memcpy( &req_hdr, ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
52 sizeof( struct atphdr ));
53 req_hdr.atphd_bitmap = ah->atph_rbitmap;
54 memcpy( ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1, &req_hdr,
55 sizeof( struct atphdr ));
57 gettimeofday( &ah->atph_reqtv, (struct timezone *)0 );
58 if ( netddp_sendto( ah->atph_socket,
59 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
60 ah->atph_reqpkt->atpbuf_dlen, 0,
61 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
62 sizeof( struct sockaddr_at )) != ah->atph_reqpkt->atpbuf_dlen ) {
66 if ( ah->atph_reqtries > 0 ) {
67 --(ah->atph_reqtries);
75 ATP ah, /* open atp handle */
76 struct sockaddr_at *faddr, /* address to receive from */
77 int func) /* which function(s) to wait for;
78 0 means request or response */
80 struct atpbuf *abuf, *pb, *cb;
81 struct atphdr req_hdr, resp_hdr;
83 int i, recvlen, requesting, mask, c;
87 struct sockaddr_at saddr;
90 atp_print_bufuse( ah, "atp_rsel at top" );
96 requesting = ( func & ATP_TRESP ) && ah->atph_rrespcount > 0 &&
97 ( ah->atph_reqtries > 0 || ah->atph_reqtries == ATP_TRIES_INFINITE );
99 if ( requesting && ah->atph_rbitmap == 0 ) {
101 * we already have a complete atp response; just return
106 if (( abuf = atp_alloc_buf()) == NULL ) {
112 printf( "<%d> atp_rsel: request pending\n", getpid());
114 gettimeofday( &tv, (struct timezone *)0 );
115 if ( tv.tv_sec - ah->atph_reqtv.tv_sec > ah->atph_reqto ) {
116 if ( resend_request( ah ) < 0 ) {
117 atp_free_buf( abuf );
127 FD_SET( ah->atph_socket, &fds );
128 tv.tv_sec = ah->atph_reqto;
130 if (( c = select( ah->atph_socket + 1, &fds, NULL, NULL,
132 atp_free_buf( abuf );
135 if ( c == 0 || FD_ISSET( ah->atph_socket, &fds ) == 0 ) {
141 memcpy( &saddr, faddr, sizeof( struct sockaddr_at ));
143 printf( "<%d> atp_rsel calling recv_atp,", getpid());
144 atp_print_addr( " accepting from: ", &saddr );
147 if (( recvlen = atp_recv_atp( ah, &saddr, &rfunc, ATP_TIDANY,
148 abuf->atpbuf_info.atpbuf_data, 0 )) >= 0 ) {
149 break; /* we received something */
153 if ( !requesting || errno != EINTR ) {
157 if ( ah->atph_reqtries <= 0 &&
158 ah->atph_reqtries != ATP_TRIES_INFINITE ) {
163 if ( resend_request( ah ) < 0 ) {
168 if ( recvlen <= 0 ) { /* error */
169 atp_free_buf( abuf );
174 printf( "<%d> atp_rsel: rcvd %d bytes", getpid(), recvlen );
175 atp_print_addr( " from: ", &saddr );
177 bprint( abuf->atpbuf_info.atpbuf_data, recvlen );
180 abuf->atpbuf_dlen = (size_t) recvlen;
181 memcpy( &resp_hdr, abuf->atpbuf_info.atpbuf_data + 1,
182 sizeof( struct atphdr ));
184 if ( rfunc == ATP_TREQ ) {
186 * we got a request: check to see if it is a duplicate (XO)
187 * while we are at it, we expire old XO responses from sent list
189 memcpy( &req_hdr, abuf->atpbuf_info.atpbuf_data + 1,
190 sizeof( struct atphdr ));
191 tid = ntohs( req_hdr.atphd_tid );
192 gettimeofday( &tv, (struct timezone *)0 );
193 for ( pb = NULL, cb = ah->atph_sent; cb != NULL;
194 pb = cb, cb = cb->atpbuf_next ) {
196 printf( "<%d>", getpid());
197 atp_print_addr( " examining", &cb->atpbuf_addr );
198 printf( " %hu", cb->atpbuf_info.atpbuf_xo.atpxo_tid );
199 atp_print_addr( " (looking for", &saddr );
200 printf( " %hu)\n", tid );
202 if ( tv.tv_sec - cb->atpbuf_info.atpbuf_xo.atpxo_tv.tv_sec
203 > cb->atpbuf_info.atpbuf_xo.atpxo_reltime ) {
204 /* discard expired response */
206 printf( "<%d> expiring tid %hu\n", getpid(),
207 cb->atpbuf_info.atpbuf_xo.atpxo_tid );
210 ah->atph_sent = cb->atpbuf_next;
212 pb->atpbuf_next = cb->atpbuf_next;
215 for ( i = 0; i < 8; ++i ) {
216 if ( cb->atpbuf_info.atpbuf_xo.atpxo_packet[ i ]
218 atp_free_buf( cb->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] );
223 if (( cb = pb ) == NULL )
226 } else if ( at_addr_eq( &saddr, &cb->atpbuf_addr )) {
227 if ( cb->atpbuf_info.atpbuf_xo.atpxo_tid == tid ) {
235 printf( "<%d> duplicate request -- re-sending XO resp\n",
238 /* matches an old response -- just re-send and reset expire */
239 cb->atpbuf_info.atpbuf_xo.atpxo_tv = tv;
240 for ( i = 0; i < 8; ++i ) {
241 if ( cb->atpbuf_info.atpbuf_xo.atpxo_packet[i] != NULL &&
242 req_hdr.atphd_bitmap & ( 1 << i )) {
243 netddp_sendto( ah->atph_socket,
244 cb->atpbuf_info.atpbuf_xo.atpxo_packet[i]->atpbuf_info.atpbuf_data,
245 cb->atpbuf_info.atpbuf_xo.atpxo_packet[i]->atpbuf_dlen,
246 0, (struct sockaddr *) &saddr, sizeof( struct sockaddr_at));
252 /* new request -- queue it and return */
253 memcpy( &abuf->atpbuf_addr, &saddr, sizeof( struct sockaddr_at ));
254 memcpy( faddr, &saddr, sizeof( struct sockaddr_at ));
255 abuf->atpbuf_next = ah->atph_queue;
256 ah->atph_queue = abuf;
259 atp_free_buf( abuf );
265 * we got a response: update bitmap
267 memcpy( &req_hdr, ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
268 sizeof( struct atphdr ));
269 if ( requesting && ah->atph_rbitmap & ( 1<<resp_hdr.atphd_bitmap )
270 && req_hdr.atphd_tid == resp_hdr.atphd_tid ) {
271 ah->atph_rbitmap &= ~( 1<<resp_hdr.atphd_bitmap );
273 if ( ah->atph_resppkt[ resp_hdr.atphd_bitmap ] != NULL ) {
274 atp_free_buf( ah->atph_resppkt[ resp_hdr.atphd_bitmap ] );
276 ah->atph_resppkt[ resp_hdr.atphd_bitmap ] = abuf;
278 /* if End Of Message, clear all higher bitmap bits
280 if ( resp_hdr.atphd_ctrlinfo & ATP_EOM ) {
282 printf( "<%d> EOM -- seq num %d current bitmap %d\n",
283 getpid(), resp_hdr.atphd_bitmap, ah->atph_rbitmap );
285 mask = 1 << resp_hdr.atphd_bitmap;
286 ah->atph_rbitmap &= ( mask | (mask-1) );
289 /* if Send Trans. Status, send updated request
291 if ( resp_hdr.atphd_ctrlinfo & ATP_STS ) {
295 req_hdr.atphd_bitmap = ah->atph_rbitmap;
296 memcpy(ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
297 &req_hdr, sizeof( struct atphdr ));
298 if ( netddp_sendto( ah->atph_socket,
299 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
300 ah->atph_reqpkt->atpbuf_dlen, 0,
301 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
302 sizeof( struct sockaddr_at )) !=
303 ah->atph_reqpkt->atpbuf_dlen ) {
304 atp_free_buf( abuf );
310 * we are not expecting this response -- toss it
312 atp_free_buf( abuf );
314 printf( "atp_rsel: ignoring resp bm=%x tid=%d (expected %x/%d)\n",
315 resp_hdr.atphd_bitmap, ntohs( resp_hdr.atphd_tid ),
316 ah->atph_rbitmap, ah->atph_tid );
320 if ( !ah->atph_rbitmap && ( req_hdr.atphd_ctrlinfo & ATP_XO )) {
322 * successful completion - send release
323 * the release consists of DDP type byte + ATP header + 4 user bytes
325 req_hdr.atphd_ctrlinfo = ATP_TREL;
326 memcpy( ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1, &req_hdr,
327 sizeof( struct atphdr ));
328 memset( ah->atph_reqpkt->atpbuf_info.atpbuf_data + ATP_HDRSIZE, 0, 4 );
329 ah->atph_reqpkt->atpbuf_dlen = sizeof( struct atphdr ) + ATP_HDRSIZE;
331 printf( "<%d> sending TREL", getpid() );
332 bprint( ah->atph_reqpkt->atpbuf_info.atpbuf_data,
333 ah->atph_reqpkt->atpbuf_dlen );
336 if (( ++release_count % 10 ) != 0 ) {
337 #endif /* DROP_ATPTREL */
338 netddp_sendto( ah->atph_socket,
339 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
340 ah->atph_reqpkt->atpbuf_dlen, 0,
341 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
342 sizeof( struct sockaddr_at));
345 #endif /* DROP_ATPTREL */
348 if ( ah->atph_rbitmap != 0 ) {
349 if ( ah->atph_reqtries > 0
350 || ah->atph_reqtries == ATP_TRIES_INFINITE ) {
358 memcpy( faddr, &saddr, sizeof( struct sockaddr_at ));