void State_ViewAbility::Update() { switch( t.Key() ){ case 'a': s.pop(); break; case 's': s.push(NEW_STATE(SwapAbility, m->pos, true)); break; } }
int CTCPConnection::Close (void) { if (m_nErrno < 0) { return m_nErrno; } switch (m_State) { case TCPStateClosed: return -1; case TCPStateListen: case TCPStateSynSent: StopTimer (TCPTimerRetransmission); NEW_STATE (TCPStateClosed); break; case TCPStateSynReceived: case TCPStateEstablished: assert (!m_bFINQueued); m_StateAfterFIN = TCPStateFinWait1; m_nRetransmissionCount = MAX_RETRANSMISSIONS; m_bFINQueued = TRUE; break; case TCPStateFinWait1: case TCPStateFinWait2: break; case TCPStateCloseWait: assert (!m_bFINQueued); m_StateAfterFIN = TCPStateLastAck; // RFC 1122 section 4.2.2.20 (a) m_nRetransmissionCount = MAX_RETRANSMISSIONS; m_bFINQueued = TRUE; break; case TCPStateClosing: case TCPStateLastAck: case TCPStateTimeWait: return -1; } if (m_nErrno < 0) { return m_nErrno; } return 0; }
CTCPConnection::CTCPConnection (CNetConfig *pNetConfig, CNetworkLayer *pNetworkLayer, CIPAddress &rForeignIP, u16 nForeignPort, u16 nOwnPort) : CNetConnection (pNetConfig, pNetworkLayer, rForeignIP, nForeignPort, nOwnPort, IPPROTO_TCP), m_bActiveOpen (TRUE), m_State (TCPStateClosed), m_nErrno (0), m_RetransmissionQueue (TCP_CONFIG_RETRANS_BUFFER_SIZE), m_bRetransmit (FALSE), m_bSendSYN (FALSE), m_bFINQueued (FALSE), m_nRetransmissionCount (0), m_bTimedOut (FALSE), m_pTimer (CTimer::Get ()), m_nSND_WND (TCP_CONFIG_WINDOW), m_nSND_UP (0), m_nRCV_NXT (0), m_nRCV_WND (TCP_CONFIG_WINDOW), m_nIRS (0), m_nSND_MSS (536) // RFC 1122 section 4.2.2.6 { m_pTxBuffer = new u8[FRAME_BUFFER_SIZE]; assert (m_pTxBuffer != 0); m_pTempBuffer = new u8[FRAME_BUFFER_SIZE]; assert (m_pTempBuffer != 0); for (unsigned nTimer = TCPTimerUser; nTimer < TCPTimerUnknown; nTimer++) { m_hTimer[nTimer] = 0; } m_nISS = CalculateISN (); m_RTOCalculator.Initialize (m_nISS); m_nSND_UNA = m_nISS; m_nSND_NXT = m_nISS+1; if (SendSegment (TCP_FLAG_SYN, m_nISS)) { m_RTOCalculator.SegmentSent (m_nISS); NEW_STATE (TCPStateSynSent); m_nRetransmissionCount = MAX_RETRANSMISSIONS; StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ()); } }
void State_Inventory::Update() { unsigned key = t.Key(); switch( key ){ case 'a': s.pop(); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if( key-48 > m->items->size() ) return; s.push(NEW_STATE(ViewItem, (*m->items)[key-49])); break; } }
int re_match(regexp_t bufp, unsigned char *string, int size, int pos, regexp_registers_t old_regs) { unsigned char *code; unsigned char *translate; unsigned char *text; unsigned char *textstart; unsigned char *textend; int a; int b; int ch; int reg; int match_end; unsigned char *regstart; unsigned char *regend; int regsize; match_state state; assert(pos >= 0 && size >= 0); assert(pos <= size); text = string + pos; textstart = string; textend = string + size; code = bufp->buffer; translate = bufp->translate; NEW_STATE(state, bufp->num_registers); continue_matching: switch (*code++) { case Cend: { match_end = text - textstart; if (old_regs) { old_regs->start[0] = pos; old_regs->end[0] = match_end; if (!bufp->uses_registers) { for (a = 1; a < RE_NREGS; a++) { old_regs->start[a] = -1; old_regs->end[a] = -1; } } else { for (a = 1; a < bufp->num_registers; a++) { if ((GET_REG_START(state, a) == NULL) || (GET_REG_END(state, a) == NULL)) { old_regs->start[a] = -1; old_regs->end[a] = -1; continue; } old_regs->start[a] = GET_REG_START(state, a) - textstart; old_regs->end[a] = GET_REG_END(state, a) - textstart; } for (; a < RE_NREGS; a++) { old_regs->start[a] = -1; old_regs->end[a] = -1; } } } FREE_STATE(state); return match_end - pos; } case Cbol: { if (text == textstart || text[-1] == '\n') goto continue_matching; goto fail; } case Ceol: { if (text == textend || *text == '\n') goto continue_matching; goto fail; } case Cset: { NEXTCHAR(ch); if (code[ch/8] & (1<<(ch & 7))) { code += 256/8; goto continue_matching; } goto fail; } case Cexact: { NEXTCHAR(ch); if (ch != (unsigned char)*code++) goto fail; goto continue_matching; } case Canychar: { NEXTCHAR(ch); if (ch == '\n') goto fail; goto continue_matching; } case Cstart_memory: { reg = *code++; SET_REG_START(state, reg, text, goto error); goto continue_matching; } case Cend_memory: { reg = *code++; SET_REG_END(state, reg, text, goto error); goto continue_matching; } case Cmatch_memory: { reg = *code++; regstart = GET_REG_START(state, reg); regend = GET_REG_END(state, reg); if ((regstart == NULL) || (regend == NULL)) goto fail; /* or should we just match nothing? */ regsize = regend - regstart; if (regsize > (textend - text)) goto fail; if(translate) { for (; regstart < regend; regstart++, text++) if (translate[*regstart] != translate[*text]) goto fail; } else for (; regstart < regend; regstart++, text++) if (*regstart != *text) goto fail; goto continue_matching; } case Cupdate_failure_jump: { UPDATE_FAILURE(state, text, goto error); /* fall to next case */ } /* treat Cstar_jump just like Cjump if it hasn't been optimized */ case Cstar_jump: case Cjump: { a = (unsigned char)*code++; a |= (unsigned char)*code++ << 8; code += (int)SHORT(a); if (code<bufp->buffer || bufp->buffer+bufp->used<code) { PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cjump)"); FREE_STATE(state); return -2; } goto continue_matching; } case Cdummy_failure_jump: { unsigned char *failuredest; a = (unsigned char)*code++; a |= (unsigned char)*code++ << 8; a = (int)SHORT(a); assert(*code == Cfailure_jump); b = (unsigned char)code[1]; b |= (unsigned char)code[2] << 8; failuredest = code + (int)SHORT(b) + 3; if (failuredest<bufp->buffer || bufp->buffer+bufp->used < failuredest) { PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cdummy_failure_jump failuredest)"); FREE_STATE(state); return -2; } PUSH_FAILURE(state, failuredest, NULL, goto error); code += a; if (code<bufp->buffer || bufp->buffer+bufp->used < code) { PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cdummy_failure_jump code)"); FREE_STATE(state); return -2; } goto continue_matching; } case Cfailure_jump: { a = (unsigned char)*code++; a |= (unsigned char)*code++ << 8; a = (int)SHORT(a); if (code+a<bufp->buffer || bufp->buffer+bufp->used < code+a) { PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Cfailure_jump)"); FREE_STATE(state); return -2; } PUSH_FAILURE(state, code + a, text, goto error); goto continue_matching; } case Crepeat1: { unsigned char *pinst; a = (unsigned char)*code++; a |= (unsigned char)*code++ << 8; a = (int)SHORT(a); pinst = code + a; if (pinst<bufp->buffer || bufp->buffer+bufp->used<pinst) { PyErr_SetString(PyExc_SystemError, "Regex VM jump out of bounds (Crepeat1)"); FREE_STATE(state); return -2; } /* pinst is sole instruction in loop, and it matches a * single character. Since Crepeat1 was originally a * Cupdate_failure_jump, we also know that backtracking * is useless: so long as the single-character * expression matches, it must be used. Also, in the * case of +, we've already matched one character, so + * can't fail: nothing here can cause a failure. */ switch (*pinst++) { case Cset: { if (translate) { while (text < textend) { ch = translate[(unsigned char)*text]; if (pinst[ch/8] & (1<<(ch & 7))) text++; else break; } } else { while (text < textend) { ch = (unsigned char)*text; if (pinst[ch/8] & (1<<(ch & 7))) text++; else break; } } break; } case Cexact: { ch = (unsigned char)*pinst; if (translate) { while (text < textend && translate[(unsigned char)*text] == ch) text++; } else { while (text < textend && (unsigned char)*text == ch) text++; } break; } case Canychar: { while (text < textend && (unsigned char)*text != '\n') text++; break; } case Csyntaxspec: { a = (unsigned char)*pinst; if (translate) { while (text < textend && (SYNTAX(translate[*text]) & a) ) text++; } else { while (text < textend && (SYNTAX(*text) & a) ) text++; } break; } case Cnotsyntaxspec: { a = (unsigned char)*pinst; if (translate) { while (text < textend && !(SYNTAX(translate[*text]) & a) ) text++; } else { while (text < textend && !(SYNTAX(*text) & a) ) text++; } break; } default: { FREE_STATE(state); PyErr_SetString(PyExc_SystemError, "Unknown regex opcode: memory corrupted?"); return -2; /*NOTREACHED*/ } } /* due to the funky way + and * are compiled, the top * failure- stack entry at this point is actually a * success entry -- update it & pop it */ UPDATE_FAILURE(state, text, goto error); goto fail; /* i.e., succeed <wink/sigh> */ } case Cbegbuf: { if (text == textstart) goto continue_matching; goto fail; } case Cendbuf: { if (text == textend) goto continue_matching; goto fail; } case Cwordbeg: { if (text == textend) goto fail; if (!(SYNTAX(*text) & Sword)) goto fail; if (text == textstart) goto continue_matching; if (!(SYNTAX(text[-1]) & Sword)) goto continue_matching; goto fail; } case Cwordend: { if (text == textstart) goto fail; if (!(SYNTAX(text[-1]) & Sword)) goto fail; if (text == textend) goto continue_matching; if (!(SYNTAX(*text) & Sword)) goto continue_matching; goto fail; } case Cwordbound: { /* Note: as in gnu regexp, this also matches at the * beginning and end of buffer. */ if (text == textstart || text == textend) goto continue_matching; if ((SYNTAX(text[-1]) & Sword) ^ (SYNTAX(*text) & Sword)) goto continue_matching; goto fail; } case Cnotwordbound: { /* Note: as in gnu regexp, this never matches at the * beginning and end of buffer. */ if (text == textstart || text == textend) goto fail; if (!((SYNTAX(text[-1]) & Sword) ^ (SYNTAX(*text) & Sword))) goto continue_matching; goto fail; } case Csyntaxspec: { NEXTCHAR(ch); if (!(SYNTAX(ch) & (unsigned char)*code++)) goto fail; goto continue_matching; } case Cnotsyntaxspec: { NEXTCHAR(ch); if (SYNTAX(ch) & (unsigned char)*code++) goto fail; goto continue_matching; } default: { FREE_STATE(state); PyErr_SetString(PyExc_SystemError, "Unknown regex opcode: memory corrupted?"); return -2; /*NOTREACHED*/ } } #if 0 /* This line is never reached --Guido */ abort(); #endif /* *NOTREACHED */ /* Using "break;" in the above switch statement is equivalent to "goto fail;" */ fail: POP_FAILURE(state, code, text, goto done_matching, goto error); goto continue_matching; done_matching: /* if(translated != NULL) */ /* free(translated); */ FREE_STATE(state); return -1; error: /* if (translated != NULL) */ /* free(translated); */ FREE_STATE(state); return -2; }
int CTCPConnection::PacketReceived (const void *pPacket, unsigned nLength, CIPAddress &rSenderIP, int nProtocol) { if (nProtocol != IPPROTO_TCP) { return 0; } if (nLength < sizeof (TTCPHeader)) { return -1; } assert (pPacket != 0); TTCPHeader *pHeader = (TTCPHeader *) pPacket; if (m_nOwnPort != be2le16 (pHeader->nDestPort)) { return 0; } if (m_State != TCPStateListen) { if ( m_ForeignIP != rSenderIP || m_nForeignPort != be2le16 (pHeader->nSourcePort)) { return 0; } } else { if (!(pHeader->nDataOffsetFlags & TCP_FLAG_SYN)) { return 0; } m_Checksum.SetDestinationAddress (rSenderIP); } if (m_Checksum.Calculate (pPacket, nLength) != CHECKSUM_OK) { return 0; } u16 nFlags = pHeader->nDataOffsetFlags; u32 nDataOffset = TCP_DATA_OFFSET (pHeader->nDataOffsetFlags)*4; u32 nDataLength = nLength-nDataOffset; // Current Segment Variables u32 nSEG_SEQ = be2le32 (pHeader->nSequenceNumber); u32 nSEG_ACK = be2le32 (pHeader->nAcknowledgmentNumber); u32 nSEG_LEN = nDataLength; if (nFlags & TCP_FLAG_SYN) { nSEG_LEN++; } if (nFlags & TCP_FLAG_FIN) { nSEG_LEN++; } u32 nSEG_WND = be2le16 (pHeader->nWindow); //u16 nSEG_UP = be2le16 (pHeader->nUrgentPointer); //u32 nSEG_PRC; // segment precedence value ScanOptions (pHeader); #ifdef TCP_DEBUG CLogger::Get ()->Write (FromTCP, LogDebug, "rx %c%c%c%c%c%c, seq %u, ack %u, win %u, len %u", nFlags & TCP_FLAG_URGENT ? 'U' : '-', nFlags & TCP_FLAG_ACK ? 'A' : '-', nFlags & TCP_FLAG_PUSH ? 'P' : '-', nFlags & TCP_FLAG_RESET ? 'R' : '-', nFlags & TCP_FLAG_SYN ? 'S' : '-', nFlags & TCP_FLAG_FIN ? 'F' : '-', nSEG_SEQ-m_nIRS, nFlags & TCP_FLAG_ACK ? nSEG_ACK-m_nISS : 0, nSEG_WND, nDataLength); DumpStatus (); #endif boolean bAcceptable = FALSE; // RFC 793 section 3.9 "SEGMENT ARRIVES" switch (m_State) { case TCPStateClosed: if (nFlags & TCP_FLAG_RESET) { // ignore } else if (!(nFlags & TCP_FLAG_ACK)) { m_ForeignIP.Set (rSenderIP); m_nForeignPort = be2le16 (pHeader->nSourcePort); m_Checksum.SetDestinationAddress (rSenderIP); SendSegment (TCP_FLAG_RESET | TCP_FLAG_ACK, 0, nSEG_SEQ+nSEG_LEN); } else { m_ForeignIP.Set (rSenderIP); m_nForeignPort = be2le16 (pHeader->nSourcePort); m_Checksum.SetDestinationAddress (rSenderIP); SendSegment (TCP_FLAG_RESET, nSEG_ACK); } break; case TCPStateListen: if (nFlags & TCP_FLAG_RESET) { // ignore } else if (nFlags & TCP_FLAG_ACK) { m_ForeignIP.Set (rSenderIP); m_nForeignPort = be2le16 (pHeader->nSourcePort); m_Checksum.SetDestinationAddress (rSenderIP); SendSegment (TCP_FLAG_RESET, nSEG_ACK); } else if (nFlags & TCP_FLAG_SYN) { m_nRCV_NXT = nSEG_SEQ+1; m_nIRS = nSEG_SEQ; m_nSND_WND = nSEG_WND; m_nSND_WL1 = nSEG_SEQ; m_nSND_WL2 = nSEG_ACK; assert (nSEG_LEN > 0); if (nDataLength > 0) { m_RxQueue.Enqueue ((u8 *) pPacket+nDataOffset, nDataLength); } m_nISS = CalculateISN (); m_RTOCalculator.Initialize (m_nISS); m_ForeignIP.Set (rSenderIP); m_nForeignPort = be2le16 (pHeader->nSourcePort); m_Checksum.SetDestinationAddress (rSenderIP); SendSegment (TCP_FLAG_SYN | TCP_FLAG_ACK, m_nISS, m_nRCV_NXT); m_RTOCalculator.SegmentSent (m_nISS); m_nSND_NXT = m_nISS+1; m_nSND_UNA = m_nISS; NEW_STATE (TCPStateSynReceived); m_Event.Set (); } break; case TCPStateSynSent: if (nFlags & TCP_FLAG_ACK) { if (!bwh (m_nISS, nSEG_ACK, m_nSND_NXT)) { if (!(nFlags & TCP_FLAG_RESET)) { SendSegment (TCP_FLAG_RESET, nSEG_ACK); } return 1; } else if (bwlh (m_nSND_UNA, nSEG_ACK, m_nSND_NXT)) { bAcceptable = TRUE; } } if (nFlags & TCP_FLAG_RESET) { if (bAcceptable) { NEW_STATE (TCPStateClosed); m_bSendSYN = FALSE; m_nErrno = -1; m_Event.Set (); } break; } if ( (nFlags & TCP_FLAG_ACK) && !bAcceptable) { break; } if (nFlags & TCP_FLAG_SYN) { m_nRCV_NXT = nSEG_SEQ+1; m_nIRS = nSEG_SEQ; if (nFlags & TCP_FLAG_ACK) { m_RTOCalculator.SegmentAcknowledged (nSEG_ACK); if (nSEG_ACK-m_nSND_UNA > 1) { m_RetransmissionQueue.Advance (nSEG_ACK-m_nSND_UNA-1); } m_nSND_UNA = nSEG_ACK; } if (gt (m_nSND_UNA, m_nISS)) { NEW_STATE (TCPStateEstablished); m_bSendSYN = FALSE; StopTimer (TCPTimerRetransmission); // next transmission starts with this count m_nRetransmissionCount = MAX_RETRANSMISSIONS; m_Event.Set (); // RFC 1122 section 4.2.2.20 (c) m_nSND_WND = nSEG_WND; m_nSND_WL1 = nSEG_SEQ; m_nSND_WL2 = nSEG_ACK; SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT); if ( (nFlags & TCP_FLAG_FIN) // other controls? || nDataLength > 0) { goto StepSix; } break; } else { NEW_STATE (TCPStateSynReceived); m_bSendSYN = FALSE; SendSegment (TCP_FLAG_SYN | TCP_FLAG_ACK, m_nISS, m_nRCV_NXT); m_RTOCalculator.SegmentSent (m_nISS); m_nRetransmissionCount = MAX_RETRANSMISSIONS; StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ()); if ( (nFlags & TCP_FLAG_FIN) // other controls? || nDataLength > 0) { if (nFlags & TCP_FLAG_FIN) { SendSegment (TCP_FLAG_RESET, m_nSND_NXT); NEW_STATE (TCPStateClosed); } if (nDataLength > 0) { m_RxQueue.Enqueue ((u8 *) pPacket+nDataOffset, nDataLength); } break; } } } break; case TCPStateSynReceived: case TCPStateEstablished: case TCPStateFinWait1: case TCPStateFinWait2: case TCPStateCloseWait: case TCPStateClosing: case TCPStateLastAck: case TCPStateTimeWait: // step 1 ( check sequence number) if (m_nRCV_WND > 0) { if (nSEG_LEN == 0) { if (bwl (m_nRCV_NXT, nSEG_SEQ, m_nRCV_NXT+m_nRCV_WND)) { bAcceptable = TRUE; } } else { if ( bwl (m_nRCV_NXT, nSEG_SEQ, m_nRCV_NXT+m_nRCV_WND) || bwl (m_nRCV_NXT, nSEG_SEQ+nSEG_LEN-1, m_nRCV_NXT+m_nRCV_WND)) { bAcceptable = TRUE; } } } else { if (nSEG_LEN == 0) { if (nSEG_SEQ == m_nRCV_NXT) { bAcceptable = TRUE; } } } if ( !bAcceptable && m_State != TCPStateSynReceived) { SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT); break; } // step 2 (check RST bit) if (nFlags & TCP_FLAG_RESET) { switch (m_State) { case TCPStateSynReceived: m_RetransmissionQueue.Flush (); if (!m_bActiveOpen) { NEW_STATE (TCPStateListen); return 1; } else { m_nErrno = -1; NEW_STATE (TCPStateClosed); m_Event.Set (); return 1; } break; case TCPStateEstablished: case TCPStateFinWait1: case TCPStateFinWait2: case TCPStateCloseWait: m_nErrno = -1; m_RetransmissionQueue.Flush (); m_TxQueue.Flush (); m_RxQueue.Flush (); NEW_STATE (TCPStateClosed); m_Event.Set (); return 1; case TCPStateClosing: case TCPStateLastAck: case TCPStateTimeWait: NEW_STATE (TCPStateClosed); m_Event.Set (); return 1; default: UNEXPECTED_STATE (); return 1; } } // step 3 (check security and precedence, not supported) // step 4 (check SYN bit) if (nFlags & TCP_FLAG_SYN) { // RFC 1122 section 4.2.2.20 (e) if ( m_State == TCPStateSynReceived && !m_bActiveOpen) { NEW_STATE (TCPStateListen); return 1; } SendSegment (TCP_FLAG_RESET, m_nSND_NXT); m_nErrno = -1; m_RetransmissionQueue.Flush (); m_TxQueue.Flush (); m_RxQueue.Flush (); NEW_STATE (TCPStateClosed); m_Event.Set (); return 1; } // step 5 (check ACK field) if (!(nFlags & TCP_FLAG_ACK)) { return 1; } switch (m_State) { case TCPStateSynReceived: if (bwlh (m_nSND_UNA, nSEG_ACK, m_nSND_NXT)) { // RFC 1122 section 4.2.2.20 (f) m_nSND_WND = nSEG_WND; m_nSND_WL1 = nSEG_SEQ; m_nSND_WL2 = nSEG_ACK; m_nSND_UNA = nSEG_ACK; // got ACK for SYN m_RTOCalculator.SegmentAcknowledged (nSEG_ACK); NEW_STATE (TCPStateEstablished); // next transmission starts with this count m_nRetransmissionCount = MAX_RETRANSMISSIONS; } else { SendSegment (TCP_FLAG_RESET, nSEG_ACK); } break; case TCPStateEstablished: case TCPStateFinWait1: case TCPStateFinWait2: case TCPStateCloseWait: case TCPStateClosing: if (bwh (m_nSND_UNA, nSEG_ACK, m_nSND_NXT)) { m_RTOCalculator.SegmentAcknowledged (nSEG_ACK); unsigned nBytesAck = nSEG_ACK-m_nSND_UNA; m_nSND_UNA = nSEG_ACK; if (nSEG_ACK == m_nSND_NXT) // all segments are acknowledged { StopTimer (TCPTimerRetransmission); // next transmission starts with this count m_nRetransmissionCount = MAX_RETRANSMISSIONS; m_Event.Set (); } if ( m_State == TCPStateFinWait1 || m_State == TCPStateClosing) { nBytesAck--; // acknowledged FIN does not count m_bFINQueued = FALSE; } if ( m_State == TCPStateEstablished && nBytesAck == 1) { nBytesAck--; } if (nBytesAck > 0) { m_RetransmissionQueue.Advance (nBytesAck); } // update send window if ( lt (m_nSND_WL1, nSEG_SEQ) || ( m_nSND_WL1 == nSEG_SEQ && le (m_nSND_WL2, nSEG_ACK))) { m_nSND_WND = nSEG_WND; m_nSND_WL1 = nSEG_SEQ; m_nSND_WL2 = nSEG_ACK; } } else if (le (nSEG_ACK, m_nSND_UNA)) // RFC 1122 section 4.2.2.20 (g) { // ignore duplicate ACK ... // RFC 1122 section 4.2.2.20 (g) if (bwlh (m_nSND_UNA, nSEG_ACK, m_nSND_NXT)) { // ... but update send window if ( lt (m_nSND_WL1, nSEG_SEQ) || ( m_nSND_WL1 == nSEG_SEQ && le (m_nSND_WL2, nSEG_ACK))) { m_nSND_WND = nSEG_WND; m_nSND_WL1 = nSEG_SEQ; m_nSND_WL2 = nSEG_ACK; } } } else if (gt (nSEG_ACK, m_nSND_NXT)) { SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT); return 1; } switch (m_State) { case TCPStateEstablished: case TCPStateCloseWait: break; case TCPStateFinWait1: if (nSEG_ACK == m_nSND_NXT) // if our FIN is now acknowledged { m_RTOCalculator.SegmentAcknowledged (nSEG_ACK); m_bFINQueued = FALSE; StopTimer (TCPTimerRetransmission); NEW_STATE (TCPStateFinWait2); } else { break; } // fall through case TCPStateFinWait2: if (m_RetransmissionQueue.IsEmpty ()) { m_Event.Set (); } break; case TCPStateClosing: if (nSEG_ACK == m_nSND_NXT) // if our FIN is now acknowledged { m_RTOCalculator.SegmentAcknowledged (nSEG_ACK); m_bFINQueued = FALSE; StopTimer (TCPTimerRetransmission); NEW_STATE (TCPStateTimeWait); StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT); } break; default: UNEXPECTED_STATE (); break; } break; case TCPStateLastAck: if (nSEG_ACK == m_nSND_NXT) // if our FIN is now acknowledged { m_bFINQueued = FALSE; NEW_STATE (TCPStateClosed); m_Event.Set (); return 1; } break; case TCPStateTimeWait: if (nSEG_ACK == m_nSND_NXT) // if our FIN is now acknowledged { m_bFINQueued = FALSE; SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT); StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT); } break; default: UNEXPECTED_STATE (); break; } // step 6 (check URG bit, not supported) StepSix: // step 7 (process text segment) if (nSEG_LEN == 0) { return 1; } switch (m_State) { case TCPStateEstablished: case TCPStateFinWait1: case TCPStateFinWait2: if (nSEG_SEQ == m_nRCV_NXT) { if (nDataLength > 0) { m_RxQueue.Enqueue ((u8 *) pPacket+nDataOffset, nDataLength); m_nRCV_NXT += nDataLength; // m_nRCV_WND should be adjusted here (section 3.7) // following ACK could be piggybacked with data SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT); if (nFlags & TCP_FLAG_PUSH) { m_Event.Set (); } } } else { SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT); } break; case TCPStateCloseWait: case TCPStateClosing: case TCPStateLastAck: case TCPStateTimeWait: break; default: UNEXPECTED_STATE (); break; } // step 8 (check FIN bit) if ( m_State == TCPStateClosed || m_State == TCPStateListen || m_State == TCPStateSynSent) { return 1; } if (!(nFlags & TCP_FLAG_FIN)) { return 1; } // connection is closing m_nRCV_NXT++; SendSegment (TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT); switch (m_State) { case TCPStateSynReceived: case TCPStateEstablished: NEW_STATE (TCPStateCloseWait); m_Event.Set (); break; case TCPStateFinWait1: if (nSEG_ACK == m_nSND_NXT) // if our FIN is now acknowledged { m_bFINQueued = FALSE; StopTimer (TCPTimerRetransmission); StopTimer (TCPTimerUser); NEW_STATE (TCPStateTimeWait); StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT); } else { NEW_STATE (TCPStateClosing); } break; case TCPStateFinWait2: StopTimer (TCPTimerRetransmission); StopTimer (TCPTimerUser); NEW_STATE (TCPStateTimeWait); StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT); break; case TCPStateCloseWait: case TCPStateClosing: case TCPStateLastAck: break; case TCPStateTimeWait: StartTimer (TCPTimerTimeWait, HZ_TIMEWAIT); break; default: UNEXPECTED_STATE (); break; } break; } return 1; }
void CTCPConnection::Process (void) { if (m_bTimedOut) { m_nErrno = -1; NEW_STATE (TCPStateClosed); m_Event.Set (); return; } switch (m_State) { case TCPStateClosed: case TCPStateListen: case TCPStateFinWait2: case TCPStateTimeWait: return; case TCPStateSynSent: case TCPStateSynReceived: if (m_bSendSYN) { m_bSendSYN = FALSE; if (m_State == TCPStateSynSent) { SendSegment (TCP_FLAG_SYN, m_nISS); } else { SendSegment (TCP_FLAG_SYN | TCP_FLAG_ACK, m_nISS, m_nRCV_NXT); } m_RTOCalculator.SegmentSent (m_nISS); StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ()); } return; case TCPStateEstablished: case TCPStateFinWait1: case TCPStateCloseWait: case TCPStateClosing: case TCPStateLastAck: if ( m_RetransmissionQueue.IsEmpty () && m_TxQueue.IsEmpty () && m_bFINQueued) { SendSegment (TCP_FLAG_FIN | TCP_FLAG_ACK, m_nSND_NXT, m_nRCV_NXT); m_RTOCalculator.SegmentSent (m_nSND_NXT); m_nSND_NXT++; NEW_STATE (m_StateAfterFIN); m_bFINQueued = FALSE; StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ()); } break; } assert (m_pTempBuffer != 0); unsigned nLength; while ( m_RetransmissionQueue.GetFreeSpace () >= FRAME_BUFFER_SIZE && (nLength = m_TxQueue.Dequeue (m_pTempBuffer)) > 0) { #ifdef TCP_DEBUG CLogger::Get ()->Write (FromTCP, LogDebug, "Transfering %u bytes into RT buffer", nLength); #endif m_RetransmissionQueue.Write (m_pTempBuffer, nLength); } if (m_bRetransmit) { #ifdef TCP_DEBUG CLogger::Get ()->Write (FromTCP, LogDebug, "Retransmission (nxt %u, una %u)", m_nSND_NXT-m_nISS, m_nSND_UNA-m_nISS); #endif m_bRetransmit = FALSE; m_RetransmissionQueue.Reset (); m_nSND_NXT = m_nSND_UNA; } u32 nBytesAvail; u32 nWindowLeft; while ( (nBytesAvail = m_RetransmissionQueue.GetBytesAvailable ()) > 0 && (nWindowLeft = m_nSND_UNA+m_nSND_WND-m_nSND_NXT) > 0) { nLength = min (nBytesAvail, nWindowLeft); nLength = min (nLength, m_nSND_MSS); #ifdef TCP_DEBUG CLogger::Get ()->Write (FromTCP, LogDebug, "Transfering %u bytes into TX buffer", nLength); #endif assert (nLength <= FRAME_BUFFER_SIZE); m_RetransmissionQueue.Read (m_pTempBuffer, nLength); unsigned nFlags = TCP_FLAG_ACK; if ( m_RetransmissionQueue.IsEmpty () && m_TxQueue.IsEmpty ()) { nFlags |= TCP_FLAG_PUSH; } SendSegment (nFlags, m_nSND_NXT, m_nRCV_NXT, m_pTempBuffer, nLength); m_RTOCalculator.SegmentSent (m_nSND_NXT, nLength); m_nSND_NXT += nLength; StartTimer (TCPTimerRetransmission, m_RTOCalculator.GetRTO ()); } }
static void register_console_config_check_commands() { cmd_info_t *showcmd, *nocmd, *confcmd, *conftcmd, *conftnocmd, *lscmd; noit_console_state_t *tl, *_conf_t_check_state, *_unset_state, *_attr_state, *_uattr_state; tl = noit_console_state_initial(); showcmd = noit_console_state_get_cmd(tl, "show"); nocmd = noit_console_state_get_cmd(tl, "no"); confcmd = noit_console_state_get_cmd(tl, "configure"); conftcmd = noit_console_state_get_cmd(confcmd->dstate, "terminal"); conftnocmd = noit_console_state_get_cmd(conftcmd->dstate, "no"); lscmd = noit_console_state_get_cmd(conftcmd->dstate, "ls"); lscmd->func = noit_console_config_show; /* attribute <attrname> <value> */ NEW_STATE(_attr_state); noit_console_state_add_check_attrs(_attr_state, noit_conf_check_set_attr, "/checks"); /* no attribute <attrname> <value> */ NEW_STATE(_uattr_state); noit_console_state_add_check_attrs(_uattr_state, noit_conf_check_unset_attr, "/checks"); NEW_STATE(_unset_state); DELEGATE_CMD(_unset_state, "attribute", noit_console_opt_delegate, _uattr_state); ADD_CMD(_unset_state, "config", noit_console_config_unsetconfig, NULL, NULL, NULL); DELEGATE_CMD(conftnocmd->dstate, "attribute", noit_console_opt_delegate, _uattr_state); ADD_CMD(conftnocmd->dstate, "config", noit_console_config_unsetconfig, NULL, NULL, NULL); ADD_CMD(conftnocmd->dstate, "check", noit_console_config_nocheck, NULL, NULL, NULL); NEW_STATE(_conf_t_check_state); _conf_t_check_state->console_prompt_function = conf_t_check_prompt; DELEGATE_CMD(_conf_t_check_state, "attribute", noit_console_opt_delegate, _attr_state); DELEGATE_CMD(_conf_t_check_state, "no", noit_console_opt_delegate, _unset_state); ADD_CMD(_conf_t_check_state, "config", noit_console_config_setconfig, NULL, NULL, NULL); ADD_CMD(_conf_t_check_state, "status", noit_console_show_check, NULL, NULL, NULL); ADD_CMD(_conf_t_check_state, "exit", noit_console_config_cd, NULL, NULL, ".."); ADD_CMD(_conf_t_check_state, "check", noit_console_check, noit_console_conf_check_opts, _conf_t_check_state, ".."); ADD_CMD(conftcmd->dstate, "config", noit_console_config_setconfig, NULL, NULL, NULL); ADD_CMD(conftcmd->dstate, "check", noit_console_check, noit_console_conf_check_opts, _conf_t_check_state, NULL); ADD_CMD(showcmd->dstate, "check", noit_console_show_check, noit_console_check_opts, NULL, NULL); ADD_CMD(tl, "watch", noit_console_watch_check, noit_console_check_opts, NULL, (void *)1); ADD_CMD(nocmd->dstate, "watch", noit_console_watch_check, noit_console_check_opts, NULL, (void *)0); DELEGATE_CMD(conftcmd->dstate, "attribute", noit_console_opt_delegate, _attr_state); ADD_CMD(tl, "reload", noit_conf_checks_reload, NULL, NULL, NULL); }