2 * Copyright (c) 1990,1997 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
13 #include <netatalk/endian.h>
14 #include <netatalk/at.h>
16 #include <atalk/netddp.h>
17 #include <atalk/compat.h>
18 #include <atalk/atp.h>
19 #include <atalk/util.h>
21 #include "atp_internals.h"
24 static int release_count = 0;
33 * update bitmap and send request packet
35 struct atphdr req_hdr;
38 printf( "\n<%d> resend_request: resending %d byte request packet",
39 getpid(), ah->atph_reqpkt->atpbuf_dlen );
40 atp_print_addr( " to", &ah->atph_reqpkt->atpbuf_addr );
42 bprint( ah->atph_reqpkt->atpbuf_info.atpbuf_data,
43 ah->atph_reqpkt->atpbuf_dlen );
46 memcpy( &req_hdr, ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
47 sizeof( struct atphdr ));
48 req_hdr.atphd_bitmap = ah->atph_rbitmap;
49 memcpy( ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1, &req_hdr,
50 sizeof( struct atphdr ));
52 gettimeofday( &ah->atph_reqtv, (struct timezone *)0 );
53 if ( netddp_sendto( ah->atph_socket,
54 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
55 ah->atph_reqpkt->atpbuf_dlen, 0,
56 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
57 sizeof( struct sockaddr_at )) != ah->atph_reqpkt->atpbuf_dlen ) {
61 if ( ah->atph_reqtries > 0 ) {
62 --(ah->atph_reqtries);
69 atp_rsel( ah, faddr, func )
70 ATP ah; /* open atp handle */
71 struct sockaddr_at *faddr; /* address to receive from */
72 int func; /* which function(s) to wait for;
73 0 means request or response */
75 struct atpbuf *abuf, *pb, *cb;
76 struct atphdr req_hdr, resp_hdr;
78 int i, recvlen, requesting, mask, c;
82 struct sockaddr_at saddr;
85 atp_print_bufuse( ah, "atp_rsel at top" );
91 requesting = ( func & ATP_TRESP ) && ah->atph_rrespcount > 0 &&
92 ( ah->atph_reqtries > 0 || ah->atph_reqtries == ATP_TRIES_INFINITE );
94 if ( requesting && ah->atph_rbitmap == 0 ) {
96 * we already have a complete atp response; just return
101 if (( abuf = atp_alloc_buf()) == NULL ) {
107 printf( "<%d> atp_rsel: request pending\n", getpid());
109 gettimeofday( &tv, (struct timezone *)0 );
110 if ( tv.tv_sec - ah->atph_reqtv.tv_sec > ah->atph_reqto ) {
111 if ( resend_request( ah ) < 0 ) {
112 atp_free_buf( abuf );
122 FD_SET( ah->atph_socket, &fds );
123 tv.tv_sec = ah->atph_reqto;
125 if (( c = select( ah->atph_socket + 1, &fds, NULL, NULL,
127 atp_free_buf( abuf );
130 if ( c == 0 || FD_ISSET( ah->atph_socket, &fds ) == 0 ) {
136 memcpy( &saddr, faddr, sizeof( struct sockaddr_at ));
138 printf( "<%d> atp_rsel calling recv_atp,", getpid());
139 atp_print_addr( " accepting from: ", &saddr );
142 if (( recvlen = atp_recv_atp( ah, &saddr, &rfunc, ATP_TIDANY,
143 abuf->atpbuf_info.atpbuf_data, 0 )) >= 0 ) {
144 break; /* we received something */
148 if ( !requesting || errno != EINTR ) {
152 if ( ah->atph_reqtries <= 0 &&
153 ah->atph_reqtries != ATP_TRIES_INFINITE ) {
158 if ( resend_request( ah ) < 0 ) {
163 if ( recvlen <= 0 ) { /* error */
164 atp_free_buf( abuf );
169 printf( "<%d> atp_rsel: rcvd %d bytes", getpid(), recvlen );
170 atp_print_addr( " from: ", &saddr );
172 bprint( abuf->atpbuf_info.atpbuf_data, recvlen );
175 abuf->atpbuf_dlen = recvlen;
176 memcpy( &resp_hdr, abuf->atpbuf_info.atpbuf_data + 1,
177 sizeof( struct atphdr ));
179 if ( rfunc == ATP_TREQ ) {
181 * we got a request: check to see if it is a duplicate (XO)
182 * while we are at it, we expire old XO responses from sent list
184 memcpy( &req_hdr, abuf->atpbuf_info.atpbuf_data + 1,
185 sizeof( struct atphdr ));
186 tid = ntohs( req_hdr.atphd_tid );
187 gettimeofday( &tv, (struct timezone *)0 );
188 for ( pb = NULL, cb = ah->atph_sent; cb != NULL;
189 pb = cb, cb = cb->atpbuf_next ) {
191 printf( "<%d>", getpid());
192 atp_print_addr( " examining", &cb->atpbuf_addr );
193 printf( " %hu", cb->atpbuf_info.atpbuf_xo.atpxo_tid );
194 atp_print_addr( " (looking for", &saddr );
195 printf( " %hu)\n", tid );
197 if ( tv.tv_sec - cb->atpbuf_info.atpbuf_xo.atpxo_tv.tv_sec
198 > cb->atpbuf_info.atpbuf_xo.atpxo_reltime ) {
199 /* discard expired response */
201 printf( "<%d> expiring tid %hu\n", getpid(),
202 cb->atpbuf_info.atpbuf_xo.atpxo_tid );
205 ah->atph_sent = cb->atpbuf_next;
207 pb->atpbuf_next = cb->atpbuf_next;
210 for ( i = 0; i < 8; ++i ) {
211 if ( cb->atpbuf_info.atpbuf_xo.atpxo_packet[ i ]
213 atp_free_buf( cb->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] );
218 if (( cb = pb ) == NULL )
221 } else if ( at_addr_eq( &saddr, &cb->atpbuf_addr )) {
222 if ( cb->atpbuf_info.atpbuf_xo.atpxo_tid == tid ) {
230 printf( "<%d> duplicate request -- re-sending XO resp\n",
233 /* matches an old response -- just re-send and reset expire */
234 cb->atpbuf_info.atpbuf_xo.atpxo_tv = tv;
235 for ( i = 0; i < 8; ++i ) {
236 if ( cb->atpbuf_info.atpbuf_xo.atpxo_packet[i] != NULL &&
237 req_hdr.atphd_bitmap & ( 1 << i )) {
238 netddp_sendto( ah->atph_socket,
239 cb->atpbuf_info.atpbuf_xo.atpxo_packet[i]->atpbuf_info.atpbuf_data,
240 cb->atpbuf_info.atpbuf_xo.atpxo_packet[i]->atpbuf_dlen,
241 0, (struct sockaddr *) &saddr, sizeof( struct sockaddr_at));
247 /* new request -- queue it and return */
248 memcpy( &abuf->atpbuf_addr, &saddr, sizeof( struct sockaddr_at ));
249 memcpy( faddr, &saddr, sizeof( struct sockaddr_at ));
250 abuf->atpbuf_next = ah->atph_queue;
251 ah->atph_queue = abuf;
254 atp_free_buf( abuf );
260 * we got a response: update bitmap
262 memcpy( &req_hdr, ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
263 sizeof( struct atphdr ));
264 if ( requesting && ah->atph_rbitmap & ( 1<<resp_hdr.atphd_bitmap )
265 && req_hdr.atphd_tid == resp_hdr.atphd_tid ) {
266 ah->atph_rbitmap &= ~( 1<<resp_hdr.atphd_bitmap );
268 if ( ah->atph_resppkt[ resp_hdr.atphd_bitmap ] != NULL ) {
269 atp_free_buf( ah->atph_resppkt[ resp_hdr.atphd_bitmap ] );
271 ah->atph_resppkt[ resp_hdr.atphd_bitmap ] = abuf;
273 /* if End Of Message, clear all higher bitmap bits
275 if ( resp_hdr.atphd_ctrlinfo & ATP_EOM ) {
277 printf( "<%d> EOM -- seq num %d current bitmap %d\n",
278 getpid(), resp_hdr.atphd_bitmap, ah->atph_rbitmap );
280 mask = 1 << resp_hdr.atphd_bitmap;
281 ah->atph_rbitmap &= ( mask | (mask-1) );
284 /* if Send Trans. Status, send updated request
286 if ( resp_hdr.atphd_ctrlinfo & ATP_STS ) {
290 req_hdr.atphd_bitmap = ah->atph_rbitmap;
291 memcpy(ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1,
292 &req_hdr, sizeof( struct atphdr ));
293 if ( netddp_sendto( ah->atph_socket,
294 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
295 ah->atph_reqpkt->atpbuf_dlen, 0,
296 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
297 sizeof( struct sockaddr_at )) !=
298 ah->atph_reqpkt->atpbuf_dlen ) {
299 atp_free_buf( abuf );
305 * we are not expecting this response -- toss it
307 atp_free_buf( abuf );
309 printf( "atp_rsel: ignoring resp bm=%x tid=%d (expected %x/%d)\n",
310 resp_hdr.atphd_bitmap, ntohs( resp_hdr.atphd_tid ),
311 ah->atph_rbitmap, ah->atph_tid );
315 if ( !ah->atph_rbitmap && ( req_hdr.atphd_ctrlinfo & ATP_XO )) {
317 * successful completion - send release
318 * the release consists of DDP type byte + ATP header + 4 user bytes
320 req_hdr.atphd_ctrlinfo = ATP_TREL;
321 memcpy( ah->atph_reqpkt->atpbuf_info.atpbuf_data + 1, &req_hdr,
322 sizeof( struct atphdr ));
323 memset( ah->atph_reqpkt->atpbuf_info.atpbuf_data + ATP_HDRSIZE, 0, 4 );
324 ah->atph_reqpkt->atpbuf_dlen = sizeof( struct atphdr ) + ATP_HDRSIZE;
326 printf( "<%d> sending TREL", getpid() );
327 bprint( ah->atph_reqpkt->atpbuf_info.atpbuf_data,
328 ah->atph_reqpkt->atpbuf_dlen );
331 if (( ++release_count % 10 ) != 0 ) {
333 netddp_sendto( ah->atph_socket,
334 ah->atph_reqpkt->atpbuf_info.atpbuf_data,
335 ah->atph_reqpkt->atpbuf_dlen, 0,
336 (struct sockaddr *) &ah->atph_reqpkt->atpbuf_addr,
337 sizeof( struct sockaddr_at));
343 if ( ah->atph_rbitmap != 0 ) {
344 if ( ah->atph_reqtries > 0
345 || ah->atph_reqtries == ATP_TRIES_INFINITE ) {
353 memcpy( faddr, &saddr, sizeof( struct sockaddr_at ));