tcpconnection.cpp
来自「SMC takes a state machine stored in a .s」· C++ 代码 · 共 1,313 行 · 第 1/3 页
CPP
1,313 行
ack_number, flags, data, offset, size); // Advance the sequence number depending on the message sent. // Don't do this if the message came from an interloper. if (recv_segment == NULL || (recv_segment->getSource()).sin_port == _farAddress.sin_port && (recv_segment->getSource()).sin_addr.s_addr == _farAddress.sin_addr.s_addr) { _sequence_number = getAck(*send_segment); } // Now send the data. First convert the TCP segment into a // sequence of raw bytes. send_segment->packetize(packet, packet_size); if (packet != NULL && packet_size > 0) {#if defined(SMC_DEBUG) cout << "**** Transmit segment:\n" << *send_segment << endl;#endif#if defined(WIN32) if (sendto(_udp_socket, packet, packet_size, NO_SEND_FLAGS, reinterpret_cast<sockaddr *>(&to_address), sizeof(to_address)) == SOCKET_ERROR)#else if (sendto(_udp_socket, packet, packet_size, NO_SEND_FLAGS, reinterpret_cast<sockaddr *>(&to_address), sizeof(to_address)) < 0)#endif { cerr << "Transmit failed - " << strerror(errno) << "." << endl; } // Free up the allocated packet. delete[] packet; } delete send_segment; return;} // end of TcpConnection::doSend(...)//---------------------------------------------------------------// startTimer(const char*, long) (Public)// Start the named timer running.//void TcpConnection::startTimer(const char *name, long duration){#if defined(SMC_DEBUG) cout << "**** Starting timer " << name << ", duration: " << duration << " milliseconds." << endl;#endif Gevent_loop->startTimer(name, duration, *this); return;} // end of TcpConnection::startTimer(const char*, long)//---------------------------------------------------------------// stopTimer(const char*) (Public)// Stop the named timer.//void TcpConnection::stopTimer(const char* name){#if defined(SMC_DEBUG) cout << "**** Stopping timer " << name << "." << endl;#endif Gevent_loop->stopTimer(name, *this); return;} // end of TcpConnection::stopTimer(const char*)//---------------------------------------------------------------// setNearAddress() (Public)// Figure out this socket's port and address based on the socket.//void TcpConnection::setNearAddress(){ // Get the UDP socket's address. _nearAddress.sin_port = AF_INET;#if defined(WIN32) _nearAddress.sin_port = _actualPort;#else _nearAddress.sin_port = getLocalPort(_udp_socket);#endif _nearAddress.sin_addr.s_addr = getLocalAddress(); return;} // end of TcpConnection::setNearAddress()//---------------------------------------------------------------// setFarAddress(const TcpSegment&) (Public)// Send data to a new client port instead of the server port.//void TcpConnection::setFarAddress(const TcpSegment& segment){ const char *data = segment.getData(); unsigned short port; _farAddress.sin_family = AF_INET; port = ((((unsigned short) data[0]) & 0x00ff) | ((((unsigned short) data[1]) & 0x00ff) << 8)); _farAddress.sin_port = port; _farAddress.sin_addr.s_addr = segment.getSource().sin_addr.s_addr; return;} // end of TcpConnection::setFarAddress(const TcpSegment&)//---------------------------------------------------------------// deleteSegment(const TcpSegment&) (Public)// Delete a segment object.//void TcpConnection::deleteSegment(const TcpSegment& segment){ delete const_cast<TcpSegment*>(&segment); return;} // end of TcpConnection::deleteSegment(const TcpSegment&)//---------------------------------------------------------------// TcpConnection(TcpConnectionListener&) (Protected)// Create a server socket.//TcpConnection::TcpConnection(TcpConnectionListener& listener): _listener(&listener),#if defined(WIN32) _actualPort(0), _udp_win_socket(NULL),#endif _udp_socket(-1), _sequence_number(ISN), _buffer(NULL), _bufferSize(0), _server(NULL), _errorMessage(NULL), _fsm(*this){ (void) memset(&_nearAddress, 0, sizeof(_nearAddress)); (void) memset(&_farAddress, 0, sizeof(_farAddress)); expandBuffer();#if defined(SMC_DEBUG) // Turn on state map debug printout. _fsm.setDebugFlag(true);#endif return;} // end of TcpConnection::TcpConnection(TcpConnectionListener&)//---------------------------------------------------------------// TcpConnection(const sockaddr_in&, ...) (Protected)// "Accepted" client connection.//TcpConnection::TcpConnection(const sockaddr_in& far_address, const sockaddr_in& near_address,#if defined(WIN32) unsigned short actual_port, SOCKET udp_socket, HANDLE udp_handle,#else int udp_socket,#endif int sequence_number, TcpServer& server, TcpConnectionListener& listener): _listener(&listener),#if defined(WIN32) _actualPort(actual_port), _udp_win_socket(udp_socket), _udp_socket((unsigned int) udp_handle),#else _udp_socket(udp_socket),#endif _sequence_number(sequence_number), _buffer(NULL), _bufferSize(0), _server(&server), _errorMessage(NULL), _fsm(*this){ // Register the UDP socket with the event loop. Gevent_loop->addFD(_udp_socket, *this); (void) memcpy(&_nearAddress, &near_address, sizeof(_nearAddress)); (void) memcpy(&_farAddress, &far_address, sizeof(_farAddress)); // Set up the input buffer. expandBuffer();#if defined(SMC_DEBUG) // Uncomment to turn on state map debug printout. _fsm.setDebugFlag(true);#endif return;} // end of TcpConnection::TcpConnection(...)//---------------------------------------------------------------// ~TcpConnection() (Protected)// Destructor.//TcpConnection::~TcpConnection(){ if (_buffer != NULL) { delete[] _buffer; _buffer = NULL; _bufferSize = 0; } if (_errorMessage != NULL) { delete[] _errorMessage; _errorMessage = NULL; } // Just in case ... closeSocket(); return;} // end of TcpConnection::~TcpConnection()//---------------------------------------------------------------// passiveOpen(unsigned short) (Protected)// Open a server socket.//void TcpConnection::passiveOpen(unsigned short port){ _fsm.PassiveOpen(port); return;} // end of TcpConnection::passiveOpen(unsigned short)//---------------------------------------------------------------// activeOpen(const sockaddr_in&) (Protected)// Open a client socket.//void TcpConnection::activeOpen(const sockaddr_in& address){ _fsm.ActiveOpen(&address); return;} // end of TcpConnection::activeOpen(const sockaddr_in&)//---------------------------------------------------------------// acceptOpen(const TcpSegment&) (Protected)// "Open" an accepted client connection.//void TcpConnection::acceptOpen(const TcpSegment& segment){ _fsm.AcceptOpen(segment); return;} // end of TcpConnection::acceptOpen(const TcpSegment&)//---------------------------------------------------------------// expandBuffer() (Private)// Expand the buffer's current size by one block.//void TcpConnection::expandBuffer(){ char *newBuffer; int newSize, currBlocks; currBlocks = _bufferSize / BUFFER_BLOCK_SIZE; newSize = (currBlocks + 1) * BUFFER_BLOCK_SIZE; newBuffer = new char[newSize]; // If the current buffer has data in it, copy it over to the // new buffer before deleting the current buffer. if (_buffer != NULL) { (void) memcpy(newBuffer, _buffer, _bufferSize); delete[] _buffer; } _buffer = newBuffer; _bufferSize = newSize; return;} // end of TcpConnection::expandBuffer()#if defined(WIN32)//---------------------------------------------------------------// doBind(int) const (Private)// Bind this UDP socket to a random, available port number.//int TcpConnection::doBind(int handle) const{ sockaddr_in address; unsigned short portIt; int socket_error, retval; // Set up this client's address. (void) memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_port = 0; address.sin_addr.s_addr = INADDR_ANY; // Start at the largest number and work down. for (portIt = MIN_PORT; portIt <= MAX_PORT; ++portIt) { address.sin_port = htons(portIt); if (bind(handle, (sockaddr *) &address, sizeof(sockaddr_in)) == SOCKET_ERROR) { socket_error = WSAGetLastError(); if (socket_error != WSAEADDRINUSE && socket_error != WSAEADDRNOTAVAIL) { retval = -1; break; } } else { // The bind worked. Return the port number. retval = address.sin_port; break; } } return(retval);} // end of TcpConnection::doBind(int) const#else//---------------------------------------------------------------// getLocalPort(int) const (Private)// Figure out the UDP socket's port number.//unsigned short TcpConnection::getLocalPort(int fd) const{ socklen_t size; sockaddr_in address; unsigned short retval; size = sizeof(address); if (getsockname(fd, reinterpret_cast<sockaddr *>(&address), &size) < 0) { retval = 0xffff; } else { retval = address.sin_port; } return(retval);} // end of TcpConnection::getLocalPort(int) const#endif//---------------------------------------------------------------// getLocalAddress() const (Private)// Return this machine's local internet address. Do this by// first retrieving the hostname and then doing gethostbyname()// on itself.//unsigned long TcpConnection::getLocalAddress() const{ char hostname[MAX_HOSTNAME_LEN]; hostent *hostEntry; unsigned long retval; // 1. Get this machine's network host name.#if defined(__sun) (void) sysinfo(SI_HOSTNAME, hostname, MAX_HOSTNAME_LEN);#else (void) gethostname(hostname, MAX_HOSTNAME_LEN);#endif // 2. Get this host name's address. if ((hostEntry = gethostbyname(hostname)) != NULL) { (void) memcpy(&retval, hostEntry->h_addr, hostEntry->h_length); } else { // If there is no known address for this host name, // default to 127.0.0.1. retval = LOCAL_HOST_ADDRESS; } return(retval);} // end of TcpConnection::getLocalAddress() const//---------------------------------------------------------------// getAck(const TcpSegment&) (Private)// Figure out what the acknowledgement number should be based on// the TCP segment's type and size.//int TcpConnection::getAck(const TcpSegment& segment){ int retval; // The ack # depends on the segment's flags. switch (segment.getFlags()) { case TcpSegment::FIN: case TcpSegment::SYN: case TcpSegment::FIN_ACK: case TcpSegment::SYN_ACK: retval = segment.getSequenceNumber() + 1; break; case TcpSegment::PSH: case TcpSegment::PSH_ACK: retval = segment.getSequenceNumber() + segment.getDataSize(); break; case TcpSegment::ACK: default: retval = segment.getSequenceNumber(); break; } return(retval);} // end of TcpConnection::getAck(const TcpSegment&)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?