Ejemplo n.º 1
0
jint limit(JNIEnv *env, jclass c, jint address) {
    NativeByteBuffer *buffer = (NativeByteBuffer *) address;
    return buffer->limit();
}
void ConnectionSocket::onEvent(uint32_t events) {
    if (events & EPOLLIN) {
        if (checkSocketError()) {
            closeSocket(1);
            return;
        } else {
            ssize_t readCount;
            NativeByteBuffer *buffer = ConnectionsManager::getInstance().networkBuffer;
            while (true) {
                buffer->rewind();
                readCount = recv(socketFd, buffer->bytes(), READ_BUFFER_SIZE, 0);
                if (readCount < 0) {
                    closeSocket(1);
                    DEBUG_E("connection(%p) recv failed", this);
                    return;
                }
                if (readCount > 0) {
                    buffer->limit((uint32_t) readCount);
                    lastEventTime = ConnectionsManager::getInstance().getCurrentTimeMonotonicMillis();
                    if (proxyAuthState == 2) {
                        if (readCount == 2) {
                            uint8_t auth_method = buffer->bytes()[1];
                            if (auth_method == 0xff) {
                                closeSocket(1);
                                DEBUG_E("connection(%p) unsupported proxy auth method", this);
                            } else if (auth_method == 0x02) {
                                DEBUG_D("connection(%p) proxy auth required", this);
                                proxyAuthState = 3;
                            } else if (auth_method == 0x00) {
                                proxyAuthState = 5;
                            }
                            adjustWriteOp();
                        } else {
                            closeSocket(1);
                            DEBUG_E("connection(%p) invalid proxy response on state 2", this);
                        }
                    } else if (proxyAuthState == 4) {
                        if (readCount == 2) {
                            uint8_t auth_method = buffer->bytes()[1];
                            if (auth_method != 0x00) {
                                closeSocket(1);
                                DEBUG_E("connection(%p) auth invalid", this);
                            } else {
                                proxyAuthState = 5;
                            }
                            adjustWriteOp();
                        } else {
                            closeSocket(1);
                            DEBUG_E("connection(%p) invalid proxy response on state 4", this);
                        }
                    } else if (proxyAuthState == 6) {
                        if (readCount > 2) {
                            uint8_t status = buffer->bytes()[1];
                            if (status == 0x00) {
                                DEBUG_D("connection(%p) connected via proxy", this);
                                proxyAuthState = 0;
                                adjustWriteOp();
                            } else {
                                closeSocket(1);
                                DEBUG_E("connection(%p) invalid proxy status on state 6, 0x%x", this, status);
                            }
                        } else {
                            closeSocket(1);
                            DEBUG_E("connection(%p) invalid proxy response on state 6", this);
                        }
                    } else if (proxyAuthState == 0) {
                        if (ConnectionsManager::getInstance().delegate != nullptr) {
                            ConnectionsManager::getInstance().delegate->onBytesReceived(readCount, currentNetworkType);
                        }
                        onReceivedData(buffer);
                    }
                }
                if (readCount != READ_BUFFER_SIZE) {
                    break;
                }
            }
        }
    }
    if (events & EPOLLOUT) {
        if (checkSocketError() != 0) {
            closeSocket(1);
            return;
        } else {
            if (proxyAuthState != 0) {
                static uint8_t buffer[1024];
                if (proxyAuthState == 1) {
                    lastEventTime = ConnectionsManager::getInstance().getCurrentTimeMonotonicMillis();
                    proxyAuthState = 2;
                    buffer[0] = 0x05;
                    buffer[1] = 0x02;
                    buffer[2] = 0x00;
                    buffer[3] = 0x02;
                    if (send(socketFd, buffer, 4, 0) < 0) {
                        DEBUG_E("connection(%p) send failed", this);
                        closeSocket(1);
                        return;
                    }
                    adjustWriteOp();
                } else if (proxyAuthState == 3) {
                    buffer[0] = 0x01;
                    uint8_t len1 = (uint8_t) ConnectionsManager::getInstance().proxyUser.length();
                    uint8_t len2 = (uint8_t) ConnectionsManager::getInstance().proxyPassword.length();
                    buffer[1] = len1;
                    memcpy(&buffer[2], ConnectionsManager::getInstance().proxyUser.c_str(), len1);
                    buffer[2 + len1] = len2;
                    memcpy(&buffer[3 + len1], ConnectionsManager::getInstance().proxyPassword.c_str(), len2);
                    proxyAuthState = 4;
                    if (send(socketFd, buffer, 3 + len1 + len2, 0) < 0) {
                        DEBUG_E("connection(%p) send failed", this);
                        closeSocket(1);
                        return;
                    }
                    adjustWriteOp();
                } else if (proxyAuthState == 5) {
                    buffer[0] = 0x05;
                    buffer[1] = 0x01;
                    buffer[2] = 0x00;
                    buffer[3] = (uint8_t) (isIpv6 ? 0x04 : 0x01);
                    uint16_t networkPort = ntohs(currentPort);
                    inet_pton(isIpv6 ? AF_INET6 : AF_INET, currentAddress.c_str(), &buffer[4]);
                    memcpy(&buffer[4 + (isIpv6 ? 16 : 4)], &networkPort, sizeof(uint16_t));
                    proxyAuthState = 6;
                    if (send(socketFd, buffer, 4 + (isIpv6 ? 16 : 4) + 2, 0) < 0) {
                        DEBUG_E("connection(%p) send failed", this);
                        closeSocket(1);
                        return;
                    }
                    adjustWriteOp();
                }
            } else {
                if (!onConnectedSent) {
                    lastEventTime = ConnectionsManager::getInstance().getCurrentTimeMonotonicMillis();
                    onConnected();
                    onConnectedSent = true;
                }
                NativeByteBuffer *buffer = ConnectionsManager::getInstance().networkBuffer;
                buffer->clear();
                outgoingByteStream->get(buffer);
                buffer->flip();

                uint32_t remaining = buffer->remaining();
                if (remaining) {
                    ssize_t sentLength;
                    if ((sentLength = send(socketFd, buffer->bytes(), remaining, 0)) < 0) {
                        DEBUG_E("connection(%p) send failed", this);
                        closeSocket(1);
                        return;
                    } else {
                        if (ConnectionsManager::getInstance().delegate != nullptr) {
                            ConnectionsManager::getInstance().delegate->onBytesSent(sentLength, currentNetworkType);
                        }
                        outgoingByteStream->discard((uint32_t) sentLength);
                        adjustWriteOp();
                    }
                }
            }
        }
    }
    if ((events & EPOLLRDHUP) || (events & EPOLLHUP)) {
        DEBUG_E("socket event has EPOLLHUP");
        closeSocket(1);
        return;
    }
    if (events & EPOLLERR) {
        DEBUG_E("connection(%p) epoll error", this);
        return;
    }
}