2 * $Id: atp_rsel.c,v 1.3.2.1 2002-02-08 00:03:27 srittau 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 */
39 * update bitmap and send request packet
41 struct atphdr req_hdr;
44 printf( "\n<%d> resend_request: resending %ld byte request packet",
45 getpid(), ah->atph_reqpkt->atpbuf_dlen );
46 atp_print_addr( " to", &ah->atph_reqpkt->atpbuf_addr );
48 bprint( ah->atph_reqpkt->atpbuf_info.atpbuf_data,
49 ah->atph_reqpkt->atpbuf_dlen );
52 memcpy( &req_hdr, ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
53 sizeof( struct atphdr ));
54 req_hdr.atphd_bitmap = ah->atph_rbitmap;
55 memcpy( ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1, &req_hdr,
56 sizeof( struct atphdr ));
58 gettimeofday( &ah->atph_reqtv, (struct timezone *)0 );
59 if ( netddp_sendto( ah->atph_socket,
60 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
61 ah->atph_reqpkt->atpbuf_dlen, 0,
62 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
63 sizeof( struct sockaddr_at )) != ah->atph_reqpkt->atpbuf_dlen ) {
67 if ( ah->atph_reqtries > 0 ) {
68 --(ah->atph_reqtries);
75 atp_rsel( ah, faddr, func )
76 ATP ah; /* open atp handle */
77 struct sockaddr_at *faddr; /* address to receive from */
78 int func; /* which function(s) to wait for;
79 0 means request or response */
81 struct atpbuf *abuf, *pb, *cb;
82 struct atphdr req_hdr, resp_hdr;
84 int i, recvlen, requesting, mask, c;
88 struct sockaddr_at saddr;
91 atp_print_bufuse( ah, "atp_rsel at top" );
97 requesting = ( func & ATP_TRESP ) && ah->atph_rrespcount > 0 &&
98 ( ah->atph_reqtries > 0 || ah->atph_reqtries == ATP_TRIES_INFINITE );
100 if ( requesting && ah->atph_rbitmap == 0 ) {
102 * we already have a complete atp response; just return
107 if (( abuf = atp_alloc_buf()) == NULL ) {
113 printf( "<%d> atp_rsel: request pending\n", getpid());
115 gettimeofday( &tv, (struct timezone *)0 );
116 if ( tv.tv_sec - ah->atph_reqtv.tv_sec > ah->atph_reqto ) {
117 if ( resend_request( ah ) < 0 ) {
118 atp_free_buf( abuf );
128 FD_SET( ah->atph_socket, &fds );
129 tv.tv_sec = ah->atph_reqto;
131 if (( c = select( ah->atph_socket + 1, &fds, NULL, NULL,
133 atp_free_buf( abuf );
136 if ( c == 0 || FD_ISSET( ah->atph_socket, &fds ) == 0 ) {
142 memcpy( &saddr, faddr, sizeof( struct sockaddr_at ));
144 printf( "<%d> atp_rsel calling recv_atp,", getpid());
145 atp_print_addr( " accepting from: ", &saddr );
148 if (( recvlen = atp_recv_atp( ah, &saddr, &rfunc, ATP_TIDANY,
149 abuf->atpbuf_info.atpbuf_data, 0 )) >= 0 ) {
150 break; /* we received something */
154 if ( !requesting || errno != EINTR ) {
158 if ( ah->atph_reqtries <= 0 &&
159 ah->atph_reqtries != ATP_TRIES_INFINITE ) {
164 if ( resend_request( ah ) < 0 ) {
169 if ( recvlen <= 0 ) { /* error */
170 atp_free_buf( abuf );
175 printf( "<%d> atp_rsel: rcvd %d bytes", getpid(), recvlen );
176 atp_print_addr( " from: ", &saddr );
178 bprint( abuf->atpbuf_info.atpbuf_data, recvlen );
181 abuf->atpbuf_dlen = (size_t) recvlen;
182 memcpy( &resp_hdr, abuf->atpbuf_info.atpbuf_data + 1,
183 sizeof( struct atphdr ));
185 if ( rfunc == ATP_TREQ ) {
187 * we got a request: check to see if it is a duplicate (XO)
188 * while we are at it, we expire old XO responses from sent list
190 memcpy( &req_hdr, abuf->atpbuf_info.atpbuf_data + 1,
191 sizeof( struct atphdr ));
192 tid = ntohs( req_hdr.atphd_tid );
193 gettimeofday( &tv, (struct timezone *)0 );
194 for ( pb = NULL, cb = ah->atph_sent; cb != NULL;
195 pb = cb, cb = cb->atpbuf_next ) {
197 printf( "<%d>", getpid());
198 atp_print_addr( " examining", &cb->atpbuf_addr );
199 printf( " %hu", cb->atpbuf_info.atpbuf_xo.atpxo_tid );
200 atp_print_addr( " (looking for", &saddr );
201 printf( " %hu)\n", tid );
203 if ( tv.tv_sec - cb->atpbuf_info.atpbuf_xo.atpxo_tv.tv_sec
204 > cb->atpbuf_info.atpbuf_xo.atpxo_reltime ) {
205 /* discard expired response */
207 printf( "<%d> expiring tid %hu\n", getpid(),
208 cb->atpbuf_info.atpbuf_xo.atpxo_tid );
211 ah->atph_sent = cb->atpbuf_next;
213 pb->atpbuf_next = cb->atpbuf_next;
216 for ( i = 0; i < 8; ++i ) {
217 if ( cb->atpbuf_info.atpbuf_xo.atpxo_packet[ i ]
219 atp_free_buf( cb->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] );
224 if (( cb = pb ) == NULL )
227 } else if ( at_addr_eq( &saddr, &cb->atpbuf_addr )) {
228 if ( cb->atpbuf_info.atpbuf_xo.atpxo_tid == tid ) {
236 printf( "<%d> duplicate request -- re-sending XO resp\n",
239 /* matches an old response -- just re-send and reset expire */
240 cb->atpbuf_info.atpbuf_xo.atpxo_tv = tv;
241 for ( i = 0; i < 8; ++i ) {
242 if ( cb->atpbuf_info.atpbuf_xo.atpxo_packet[i] != NULL &&
243 req_hdr.atphd_bitmap & ( 1 << i )) {
244 netddp_sendto( ah->atph_socket,
245 cb->atpbuf_info.atpbuf_xo.atpxo_packet[i]->atpbuf_info.atpbuf_data,
246 cb->atpbuf_info.atpbuf_xo.atpxo_packet[i]->atpbuf_dlen,
247 0, (struct sockaddr *) &saddr, sizeof( struct sockaddr_at));
253 /* new request -- queue it and return */
254 memcpy( &abuf->atpbuf_addr, &saddr, sizeof( struct sockaddr_at ));
255 memcpy( faddr, &saddr, sizeof( struct sockaddr_at ));
256 abuf->atpbuf_next = ah->atph_queue;
257 ah->atph_queue = abuf;
260 atp_free_buf( abuf );
266 * we got a response: update bitmap
268 memcpy( &req_hdr, ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
269 sizeof( struct atphdr ));
270 if ( requesting && ah->atph_rbitmap & ( 1<<resp_hdr.atphd_bitmap )
271 && req_hdr.atphd_tid == resp_hdr.atphd_tid ) {
272 ah->atph_rbitmap &= ~( 1<<resp_hdr.atphd_bitmap );
274 if ( ah->atph_resppkt[ resp_hdr.atphd_bitmap ] != NULL ) {
275 atp_free_buf( ah->atph_resppkt[ resp_hdr.atphd_bitmap ] );
277 ah->atph_resppkt[ resp_hdr.atphd_bitmap ] = abuf;
279 /* if End Of Message, clear all higher bitmap bits
281 if ( resp_hdr.atphd_ctrlinfo & ATP_EOM ) {
283 printf( "<%d> EOM -- seq num %d current bitmap %d\n",
284 getpid(), resp_hdr.atphd_bitmap, ah->atph_rbitmap );
286 mask = 1 << resp_hdr.atphd_bitmap;
287 ah->atph_rbitmap &= ( mask | (mask-1) );
290 /* if Send Trans. Status, send updated request
292 if ( resp_hdr.atphd_ctrlinfo & ATP_STS ) {
296 req_hdr.atphd_bitmap = ah->atph_rbitmap;
297 memcpy(ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
298 &req_hdr, sizeof( struct atphdr ));
299 if ( netddp_sendto( ah->atph_socket,
300 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
301 ah->atph_reqpkt->atpbuf_dlen, 0,
302 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
303 sizeof( struct sockaddr_at )) !=
304 ah->atph_reqpkt->atpbuf_dlen ) {
305 atp_free_buf( abuf );
311 * we are not expecting this response -- toss it
313 atp_free_buf( abuf );
315 printf( "atp_rsel: ignoring resp bm=%x tid=%d (expected %x/%d)\n",
316 resp_hdr.atphd_bitmap, ntohs( resp_hdr.atphd_tid ),
317 ah->atph_rbitmap, ah->atph_tid );
321 if ( !ah->atph_rbitmap && ( req_hdr.atphd_ctrlinfo & ATP_XO )) {
323 * successful completion - send release
324 * the release consists of DDP type byte + ATP header + 4 user bytes
326 req_hdr.atphd_ctrlinfo = ATP_TREL;
327 memcpy( ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1, &req_hdr,
328 sizeof( struct atphdr ));
329 memset( ah->atph_reqpkt->atpbuf_info.atpbuf_data + ATP_HDRSIZE, 0, 4 );
330 ah->atph_reqpkt->atpbuf_dlen = sizeof( struct atphdr ) + ATP_HDRSIZE;
332 printf( "<%d> sending TREL", getpid() );
333 bprint( ah->atph_reqpkt->atpbuf_info.atpbuf_data,
334 ah->atph_reqpkt->atpbuf_dlen );
337 if (( ++release_count % 10 ) != 0 ) {
338 #endif /* DROP_ATPTREL */
339 netddp_sendto( ah->atph_socket,
340 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
341 ah->atph_reqpkt->atpbuf_dlen, 0,
342 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
343 sizeof( struct sockaddr_at));
346 #endif /* DROP_ATPTREL */
349 if ( ah->atph_rbitmap != 0 ) {
350 if ( ah->atph_reqtries > 0
351 || ah->atph_reqtries == ATP_TRIES_INFINITE ) {
359 memcpy( faddr, &saddr, sizeof( struct sockaddr_at ));