📄 dirsend.c
字号:
/* - - - - - - - - *//* * This routine is called when a timeout occurs. It includes the code that * was formerly used when select() returned 0 (indicating a timeout). *//*ARGSUSED*/static voidtimeoutProc(client_data,id)XtPointer client_data;XtIntervalId *id;{ if (gaps || ackpend) { /* Send acknowledgment */ /* Acks are piggybacked on retries - If we have received */ /* an ack from the server, then the packet sent is only */ /* an ack and the rest of the message will be empty */#ifdef DEBUG if (pfs_debug > 2) { fprintf(stderr,"Acknowledging (%s).\n", (ackpend ? "requested" : "gaps")); } #endif if (gaps && verbose) fprintf (stderr, "Searching...\n"); retryDirsend(); return; } if (retries-- > 0) { timeout.tv_sec = CLIENT_DIRSRV_BACKOFF(timeout.tv_sec);#ifdef DEBUG if (pfs_debug > 2) { fprintf(stderr,"Timed out. Setting timeout to %d seconds.\n", (int)timeout.tv_sec); }#endif retryDirsend(); return; }#ifdef DEBUG if (pfs_debug) { fprintf(stderr, "select failed(timeoutProc): readfds=%x ", *(int *)&readfds); perror(""); }#endif close(lp); perrno = DIRSEND_SELECT_FAILED; ptlfree(first); ptlfree(pkt); /* return(NULL); */ dirsendReturn = NULL; dirsendDone = DSRET_TIMEOUT;}/* - - - - - - - - *//* * This function is called whenever there's something to read on the * connection. It includes the code that was run when select() returned * greater than 0 (indicating read ready). *//*ARGSUSED*/static voidreadProc(client_data,source,id)XtPointer client_data;int *source;XtInputId *id;{ from_sz = sizeof(from); next->start = next->dat; if ((nr = recvfrom(lp, next->start, sizeof(next->dat), 0, (struct sockaddr *)&from, &from_sz)) < 0) {#ifdef DEBUG if (pfs_debug) perror("recvfrom");#endif close(lp); perrno = DIRSEND_BAD_RECV; ptlfree(first); ptlfree(pkt); /* return(NULL) */ dirsendReturn = NULL; dirsendDone = DSRET_RECV_ERROR; return; } next->length = nr; next->start[next->length] = 0;#ifdef DEBUG if (pfs_debug > 2) fprintf(stderr,"Received packet from %s\n", inet_ntoa(from.sin_addr));#endif /* For the current format, if the first byte is less than */ /* 20, then the first two bits are a version number and the next six */ /* are the header length (including the first byte). */ if((hdr_len = (unsigned char) *(next->start)) < 20) { ctlptr = next->start + 1; next->seq = 0; if(hdr_len >= 3) { /* Connection ID */ bcopy(ctlptr, (char *)&stmp,2); if(stmp) pkt_cid = ntohs(stmp); ctlptr += 2; } if (pkt_cid<0) pkt_cid = 65536+pkt_cid; if(pkt_cid && this_conn_id && (pkt_cid != ntohs(this_conn_id))) { /* The packet is not for us */ /* goto keep_waiting; */#ifdef DEBUG if (pfs_debug > 20) fprintf(stderr,"Packet not for us %d,%d,%d\n", pkt_cid,this_conn_id,ntohs(this_conn_id));#endif keepWaitingDirsend(); return; } if(hdr_len >= 5) { /* Packet number */ bcopy(ctlptr, (char *)&stmp,2); next->seq = ntohs(stmp); ctlptr += 2; } else { /* No packet number specified, so this is the only one */ next->seq = 1; nd_pkts = 1; } if(hdr_len >= 7) { /* Total number of packets */ bcopy(ctlptr, (char *)&stmp,2); /* 0 means don't know */ if(stmp) nd_pkts = ntohs(stmp); ctlptr += 2; } if(hdr_len >= 9) { /* Receievd through */ bcopy(ctlptr, (char *)&stmp,2); /* 1 means received request */#ifndef USE_V3_PROT if((stmp) && (ntohs(stmp) == 1)) { /* Future retries will be acks only */ pkt->length = 9; bcopy((char *)&zero, pkt->start+3,2);#ifdef DEBUG if(pfs_debug > 2) fprintf(stderr,"Server acked request - retries will be acks only\n");#endif }#endif ctlptr += 2; } if(hdr_len >= 11) { /* Backoff */ bcopy(ctlptr, (char *)&stmp,2); if(stmp) { backoff = (short) ntohs(stmp);#ifdef DEBUG if(pfs_debug > 2) fprintf(stderr,"Backing off to %d seconds\n", backoff);#endif timeout.tv_sec = backoff; if ((backoff > 60) && (first == next) && (no_pkts == 0)) { /* Probably a long queue on the server - don't give up */ retries = client_dirsrv_retry; } } ctlptr += 2; } if(hdr_len >= 12) { /* Flags (1st byte) */ bcopy(ctlptr, (char *)&rdflag11,1); if(rdflag11 & 0x80) {#ifdef DEBUG if(pfs_debug > 2) fprintf(stderr,"Ack requested\n");#endif ackpend++; } if(rdflag11 & 0x40) {#ifdef DEBUG if(pfs_debug > 2) fprintf(stderr,"Sequenced control packet\n");#endif next->length = -1; scpflag++; } ctlptr += 1; } if(hdr_len >= 13) { /* Flags (2nd byte) */ /* Reserved for future use */ bcopy(ctlptr, (char *)&rdflag12,1); ctlptr += 1; } if(next->seq == 0) { /* goto keep_waiting; */ keepWaitingDirsend(); return; } if(next->length >= 0) next->length -= hdr_len; next->start += hdr_len; goto done_old; } pkt_cid = 0; /* if intermediate format (between old and new), then process */ /* and go to done_old */ ctlptr = next->start + max(0,next->length-20); while(*ctlptr) ctlptr++; /* Control fields start after the terminating null */ ctlptr++; /* Until old version are gone, must be 4 extra bytes minimum */ /* When no version 3 servers, can remove the -4 */ if(ctlptr < (next->start + next->length - 4)) { /* Connection ID */ bcopy(ctlptr, (char *)&stmp,2); if(stmp) pkt_cid = ntohs(stmp); ctlptr += 2; if(pkt_cid && this_conn_id && (pkt_cid != ntohs(this_conn_id))) { /* The packet is not for us */ /* goto keep_waiting; */ keepWaitingDirsend(); return; } /* Packet number */ if(ctlptr < (next->start + next->length)) { bcopy(ctlptr, (char *)&stmp,2); next->seq = ntohs(stmp); ctlptr += 2; } /* Total number of packets */ if(ctlptr < (next->start + next->length)) { bcopy(ctlptr, (char *)&stmp,2); if(stmp) nd_pkts = ntohs(stmp); ctlptr += 2; } /* Receievd through */ if(ctlptr < (next->start + next->length)) { /* Not supported by clients */ ctlptr += 2; } /* Backoff */ if(ctlptr < (next->start + next->length)) { bcopy(ctlptr, (char *)&stmp,2); backoff = ntohs(stmp);#ifdef DEBUG if(pfs_debug > 2) fprintf(stderr,"Backing off to %d seconds\n", backoff);#endif if (verbose && backoff) fprintf (stderr, "Searching...\n"); if(backoff) timeout.tv_sec = backoff; ctlptr += 2; } if(next->seq == 0) { /* goto keep_waiting; */ keepWaitingDirsend(); return; } goto done_old; } /* Notes that we have to start searching 11 bytes before the */ /* expected start of the MULTI-PACKET line because the message */ /* might include up to 10 bytes of data after the trailing null */ /* The order of those bytes is two bytes each for Connection ID */ /* Packet-no, of, Received-through, Backoff */ seqtxt = nlsindex(next->start + max(0,next->length - 40),"MULTI-PACKET"); if(seqtxt) seqtxt+= 13; if((nd_pkts == 0) && (no_pkts == 0) && (seqtxt == NULL)) goto all_done; tmp = sscanf(seqtxt,"%d OF %d", &(next->seq), &nd_pkts);#ifdef DEBUG if (pfs_debug && (tmp == 0)) fprintf(stderr,"Cant read packet sequence number: %s", seqtxt); #endif done_old:#ifdef DEBUG if(pfs_debug > 2) fprintf(stderr,"Packet %d of %d\n",next->seq,nd_pkts);#endif if ((first == next) && (no_pkts == 0)) { if(first->seq == 1) { comp_thru = first; /* If only one packet, then return it */ if(nd_pkts == 1) goto all_done; } else gaps++; no_pkts = 1; next = ptalloc(); /* goto keep_waiting; */ keepWaitingDirsend(); return; } if(comp_thru && (next->seq <= comp_thru->seq)) ptfree(next); else if (next->seq < first->seq) { vtmp = first; first = next; first->next = vtmp; first->previous = NULL; vtmp->previous = first; if(first->seq == 1) comp_thru = first; no_pkts++; } else { vtmp = (comp_thru ? comp_thru : first); while (vtmp->seq < next->seq) { if(vtmp->next == NULL) { vtmp->next = next; next->previous = vtmp; next->next = NULL; no_pkts++; goto ins_done; } vtmp = vtmp->next; } if(vtmp->seq == next->seq) ptfree(next); else { vtmp->previous->next = next; next->previous = vtmp->previous; next->next = vtmp; vtmp->previous = next; no_pkts++; } } ins_done: while(comp_thru && comp_thru->next && (comp_thru->next->seq == (comp_thru->seq + 1))) { comp_thru = comp_thru->next;#ifndef USE_V3_PROT recvd_thru = htons(comp_thru->seq); bcopy((char *)&recvd_thru,pkt->start+7,2); /* Let server know we got it */#endif /* We've made progress, so reset retry count */ retries = client_dirsrv_retry; /* Also, next retry will be only an acknowledgement */ /* but for now, we can't fill in the ack field */#ifdef DEBUG if(pfs_debug > 2) fprintf(stderr,"Packets now received through %d\n",comp_thru->seq);#endif } /* See if there are any gaps */ if(!comp_thru || comp_thru->next) gaps++; else gaps = 0; if ((nd_pkts == 0) || (no_pkts < nd_pkts)) { next = ptalloc(); /* goto keep_waiting; */ keepWaitingDirsend(); return; } all_done: if(ackpend) { /* Send acknowledgement if requested */#ifdef DEBUG if (pfs_debug > 2) { if (to.sin_family == AF_INET) fprintf(stderr,"Acknowledging final packet to %s(%d)\n", to_hostname, ntohs(this_conn_id)); else fprintf(stderr,"Acknowledging final packet\n"); (void) fflush(stderr); }#endif ns = sendto(lp,(char *)(pkt->start), pkt->length, 0, (struct sockaddr *)&to, S_AD_SZ); if(ns != pkt->length) {#ifdef DEBUG if (pfs_debug) { fprintf(stderr,"\nsent only %d/%d: ",ns, pkt->length); perror(""); }#endif } } close(lp); ptlfree(pkt); /* Get rid of any sequenced control packets */ if(scpflag) { while(first && (first->length < 0)) { vtmp = first; first = first->next; if(first) first->previous = NULL; ptfree(vtmp); } vtmp = first; while(vtmp && vtmp->next) { if(vtmp->next->length < 0) { if(vtmp->next->next) { vtmp->next = vtmp->next->next; ptfree(vtmp->next->previous); vtmp->next->previous = vtmp; } else { ptfree(vtmp->next); vtmp->next = NULL; } } vtmp = vtmp->next; } } /* return(first); */ dirsendReturn = first; dirsendDone = DSRET_DONE;}static voidprocessEvent(){ /* select - either recv is ready, or timeout */ /* see if timeout or error or wrong descriptor */ tmp = select(lp + 1, &readfds, (SELECTARG *)0, (SELECTARG *)0, selwait); if (tmp == 0) { timeoutProc(NULL,&timerId); } else if ((tmp < 0) || !FD_ISSET(lp,&readfds)) {#ifdef DEBUG if (pfs_debug) { fprintf(stderr, "select failed(processEvent): readfds=%x ", *(int *)&readfds); perror(""); }#endif close(lp); perrno = DIRSEND_SELECT_FAILED; ptlfree(first); ptlfree(pkt); /* return(NULL); */ dirsendReturn = NULL; dirsendDone = DSRET_SELECT_ERROR; } else { readProc(NULL,&lp,&inputId); }}voidabortDirsend(){ if (!dirsendDone) { close(lp); ptlfree(first); ptlfree(pkt); dirsendReturn = NULL; dirsendDone = DSRET_ABORTED; } return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -