📄 http_connect.c
字号:
break; case SYN: { /* In some cases the same host/port pairs are reused in a single trace; check for plausible reuse */ check_tuple_reuse(); break; } case ACK_ONLY: /* an ACK might advance possibly indicating a request. However, since the connection is Reset and there should be no new response, just ignore it */ break; case FIN: { /* Only if the state is IN_RESPONSE do we try to continue looking for the end of the response. FIN is treated as the true end of a response. */ if (last_state == IN_RESPONSE) {/* ends the current response, ignore any ACK */ if ((has_seq == 1) && (end_seq > current_response_end)) more_RSP(); log_RSP(); last_state = RESET; connection_state = FIN_SENT; /* record timestamp of first FIN on connection */ if (strcmp(FIN_sent_time, "") == 0) strcpy(FIN_sent_time, ts); } break; } case DATA_ACK: { /* segments with data may advance the data sequence number as more parts of the response. They may also advance the ACK which normally would indicate a new request. However, after a Reset, it probably will be ignored by the server so it is also ignored here except to mark the end of the response. */ if (last_state == IN_RESPONSE) { if (new_ack > (last_request_end + 1)) /* new request */ { /* implies end of current response */ log_RSP(); last_state = RESET; /* will ignore all else */ break; } /* As long as the data sequence # advances, continue to save info about the current response. */ if ((end_seq > current_response_end) && (seq_bytes > 0)) more_RSP(); } break; } default: break; } /* end switch on input type */ break; } /* end case RESET */ case IN_RESPONSE: { /* In this state, look for events that will indicate the end of the response data (ACK advances for request, FIN, Reset). If the event is ACK advance, this also initiates the start of a new request. */ switch (input_type) { case FIN: { /* FIN is complicated since the segment that carries it may also advance the ACK (new request), advance the data sequence # and end the connection. If the ACK advances, any sequence # advance is for the new request; otherwise a sequence # advance extends and completes the current response. */ if (has_ack == 1) { if ((rc = check_ACK_advance(current_request_end)) < 0) break; } /* The ACK advance amount has to be greater than 1 to be considered a real new request. This is primarily to filter out just an ACK for a FIN from the client. Note the ACK must advance so duplicate ACKs are ignored. */ if ((has_ack == 1) && (new_ack > (current_request_end + 1))) { /* implies end of current response, begin request Log the info. for the current response. */ log_RSP(); /*end of previous response */ /* on FIN, assume end of request also since server is closing the connection. */ begin_REQ(); log_REQ(); /* if the data sequence # also advances, this segment (only -- because of the FIN) carries the last part of the response */ if ((has_seq == 1) && (end_seq > last_response_end)) {/* response begins and ends in the FIN segment */ begin_RSP(); log_RSP(); /* also end of any response */ } /* Note that the null "else" here is the case that the data sequence # does not advance (there is no response to the request) -- probably an HTTP/1.1 broswer attempting multiple requests on a TCP connection where the server doesn't play nice. */ } else /* the ACK did not advance so no request; if the data sequence # advances, it extends the current response */ { if ((has_seq == 1) && (end_seq > current_response_end)) more_RSP(); log_RSP(); /* FIN always implies end of response */ } last_state = IN_RESPONSE; connection_state = FIN_SENT; if (strcmp(FIN_sent_time, "") == 0) strcpy(FIN_sent_time, ts); break; } case RST: /* Look for a Reset and only change state to RESET to continue processing. This is explained in comments in processing for the RESET state when the last_state is IN_RESPONSE. */ {/* ignore any advance in seq# on Reset */ /* it may not be wise to trust ACK on RST */ last_state = IN_RESPONSE; connection_state = RESET; if (strcmp(RST_sent_time, "") == 0) strcpy(RST_sent_time, ts); break; } case SYN: { /* In some cases the same host/port pairs are reused in a single trace; check for plausible reuse */ check_tuple_reuse(); break; } case ACK_ONLY: /* Begin checking for cases where the ACK may advance and really indicate that a new request starts. */ { /* The ACK advance amount has to be greater than 1 to be considered a real new request. This is primarily to filter out just an ACK for a FIN from the client. Note the ACK must advance so duplicate or OOO ACKs are ignored. */ if (new_ack > (last_request_end + 1)) { /* implies end of current response, begin request. Log the info. for the current response and change states. */ log_RSP(); /* since there is no data sequence # present in the record and, therefore, the server is not sending data so all the client's data may not have arrived. Note the current extent of ACKed client data and start time */ begin_REQ(); } break; } case DATA_ACK: /* cases with data and ACKs have two important sub-cases: (a) ACK sequence number advances -- implies the start of a new request and the end of the current response; if the data sequence number also advances, it is assumed that all the request data has been received and the first of the response data is contained in the segment. (b) the ACK sequence number does not advance so any advance in the data sequence number is more of the current response. */ { if ((rc = check_ACK_advance(last_request_end)) < 0) break; /* The ACK advance amount has to be greater than 1 to be considered a real new request. This is primarily to filter out just an ACK for a FIN from the client. Note the ACK must advance so duplicate ACKs are ignored. */ if (new_ack > (last_request_end + 1)) { /* implies end of current response, begin request Log the info. for the current response. */ log_RSP(); begin_REQ(); /* If there is also new data (sequence # advances), then the request is considered completed and a new response has started but not necessarily completed. */ if ((end_seq > current_response_end) && (seq_bytes > 0)) {/* Log info. about this request */ log_REQ(); begin_RSP(); } } else /* the ACK did not advance so no request; if the data sequence # advances, it extends the current response */ if (end_seq > current_response_end) more_RSP(); break; } default: break; } /* end switch on input type */ break; } /* end case IN_RESPONSE */ case IN_REQUEST: { /* In this state check for events that indicate the end of the request data (advance of data sequence #, FIN, Reset). An advance in the data sequence # also marks the beginning of the response to the request */ switch (input_type) { case FIN: /* FIN is somewhat less complicated here since the segment that implies that the server will send no more data. Treat this as effectively ending the request. If the ACK advances, it is considered as part of the request and if the data sequence # advances, it is the response data (all in this segment). */ { /* FIN can ACK more of current request */ /* The ACK advance amount has to be greater than 1 to be considered as extending the request. This is primarily to filter out just an ACK for a FIN from the client. Note the ACK must advance so duplicate ACKs are ignored. */ if ((has_ack == 1) && (new_ack > (current_request_end + 1))) more_REQ(); else if (has_ack == 1) { if ((rc = check_ACK_advance(current_request_end)) < 0) break; } log_REQ(); /* on FIN, assume end of request */ /* the server's data sequence may not have advanced; but if it has, treat it as the complete response */ if ((has_seq == 1) && (end_seq > last_response_end)) { begin_RSP(); log_RSP(); /* also end of any response */ } last_state = IN_REQUEST; connection_state = FIN_SENT; if (strcmp(FIN_sent_time, "") == 0) strcpy(FIN_sent_time, ts); break; } case RST: { /* Treat a Reset as ending the request with no response */ /* ignore any advance in ack on Reset */ /* treat as ending any request */ log_REQ(); last_state = IN_REQUEST; connection_state = RESET; if (strcmp(RST_sent_time, "") == 0) strcpy(RST_sent_time, ts); break; } case SYN: { /* In some cases the same host/port pairs are reused in a single trace; check for plausible reuse */ check_tuple_reuse(); break; } case ACK_ONLY: { /* The ACK advance amount has to be greater than 1 to be considered as extending the requesst. This is primarily to filter out just an ACK for a FIN from the client. Note the ACK must advance so duplicate or OOO ACKs are ignored. */ if (new_ack > (current_request_end + 1)) more_REQ(); break; } case DATA_ACK: { /* cases with data and ACKs have two important sub-cases: (a) ACK sequence number advances which extends the amount of request data, and (b) the data sequence # advances which ends the request and is the beginning of the response to that request. */ /* The ACK advance amount has to be greater than 1 to be considered as extending the request. This is primarily to filter out just an ACK for a FIN from the client. Note the ACK must advance so duplicate ACKs are ignored. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -