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 + -
显示快捷键?