static int swClient_tcp_connect_sync(swClient *cli, char *host, int port, double timeout, int nonblock) { int ret; cli->timeout = timeout; if (swClient_inet_addr(cli, host, port) < 0) { return SW_ERR; } if (nonblock == 1) { swSetNonBlock(cli->socket->fd); } else { if (cli->timeout > 0) { swSocket_set_timeout(cli->socket->fd, timeout); } swSetBlock(cli->socket->fd); } while (1) { ret = connect(cli->socket->fd, (struct sockaddr *) &cli->server_addr.addr, cli->server_addr.len); if (ret < 0) { if (errno == EINTR) { continue; } } break; } if (ret >= 0) { cli->socket->active = 1; #ifdef SW_USE_OPENSSL if (cli->open_ssl) { if (swClient_enable_ssl_encrypt(cli) < 0) { return SW_ERR; } if (swClient_ssl_handshake(cli) < 0) { return SW_ERR; } } #endif } return ret; }
static int swClient_onWrite(swReactor *reactor, swEvent *event) { swClient *cli = event->socket->object; if (cli->socket->active) { #ifdef SW_USE_OPENSSL if (cli->open_ssl && cli->socket->ssl_state == SW_SSL_STATE_WAIT_STREAM) { if (swClient_ssl_handshake(cli) < 0) { goto connect_fail; } else if (cli->socket->ssl_state == SW_SSL_STATE_READY) { goto connect_success; } else { return SW_OK; } } #endif return swReactor_onWrite(SwooleG.main_reactor, event); } int error; socklen_t len = sizeof(error); if (getsockopt (event->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { swWarn("getsockopt(%d) failed. Error: %s[%d]", event->fd, strerror(errno), errno); return SW_ERR; } //success if (error == 0) { //listen read event SwooleG.main_reactor->set(SwooleG.main_reactor, event->fd, (SW_FD_USER + 1) | SW_EVENT_READ); //connected cli->socket->active = 1; #ifdef SW_USE_OPENSSL if (cli->open_ssl) { if (swClient_enable_ssl_encrypt(cli) < 0) { goto connect_fail; } if (swClient_ssl_handshake(cli) < 0) { goto connect_fail; } else { cli->socket->ssl_state = SW_SSL_STATE_WAIT_STREAM; } return SW_OK; } connect_success: #endif if (cli->onConnect) { cli->onConnect(cli); } } else { #ifdef SW_USE_OPENSSL connect_fail: #endif cli->close(cli); if (cli->onError) { cli->onError(cli); } } return SW_OK; }
static int swClient_onStreamRead(swReactor *reactor, swEvent *event) { int n; swClient *cli = event->socket->object; char *buf = cli->buffer->str; long buf_size = cli->buffer->size; if (cli->socks5_proxy && cli->socks5_proxy->state != SW_SOCKS5_STATE_READY) { int n = swConnection_recv(event->socket, buf, buf_size, 0); if (n <= 0) { goto __close; } if (swSocks5_connect(cli, buf, buf_size) < 0) { goto __close; } if (cli->socks5_proxy->state != SW_SOCKS5_STATE_READY) { return SW_OK; } #ifdef SW_USE_OPENSSL if (cli->open_ssl) { if (swClient_enable_ssl_encrypt(cli) < 0) { connect_fail: cli->close(cli); if (cli->onError) { cli->onError(cli); } } else { if (swClient_ssl_handshake(cli) < 0) { goto connect_fail; } else { cli->socket->ssl_state = SW_SSL_STATE_WAIT_STREAM; } return SwooleG.main_reactor->set(SwooleG.main_reactor, event->fd, SW_FD_STREAM_CLIENT | SW_EVENT_WRITE); } } else #endif { cli->onConnect(cli); } return SW_OK; } #ifdef SW_USE_OPENSSL if (cli->open_ssl && cli->socket->ssl_state == SW_SSL_STATE_WAIT_STREAM) { if (swClient_ssl_handshake(cli) < 0) { return cli->close(cli); } if (cli->socket->ssl_state != SW_SSL_STATE_READY) { return SW_OK; } //ssl handshake sucess else if (cli->onConnect) { cli->onConnect(cli); } } #endif /** * redirect stream data to other socket */ if (cli->redirect) { int ret = 0; n = swConnection_recv(event->socket, buf, buf_size, 0); if (n < 0) { goto __error; } else if (n == 0) { goto __close; } if (cli->_redirect_to_socket) { ret = SwooleG.main_reactor->write(SwooleG.main_reactor, cli->_redirect_to_socket, buf, n); } else if (cli->_redirect_to_session) { if (SwooleG.serv->send(SwooleG.serv, cli->_redirect_to_session, buf, n) < 0) { if (SwooleG.error >= SW_ERROR_SESSION_CLOSED_BY_SERVER || SwooleG.error >= SW_ERROR_SESSION_INVALID_ID) { goto __close; } } else { return SW_OK; } } else { ret = swSocket_write_blocking(cli->_redirect_to_file, buf, n); } if (ret < 0) { goto __error; } return SW_OK; } if (cli->open_eof_check || cli->open_length_check) { swConnection *conn = cli->socket; swProtocol *protocol = &cli->protocol; if (cli->open_eof_check) { n = swProtocol_recv_check_eof(protocol, conn, cli->buffer); } else { n = swProtocol_recv_check_length(protocol, conn, cli->buffer); } if (n < 0) { return cli->close(cli); } else { return SW_OK; } } #ifdef SW_CLIENT_RECV_AGAIN recv_again: #endif n = swConnection_recv(event->socket, buf, buf_size, 0); if (n < 0) { __error: switch (swConnection_error(errno)) { case SW_ERROR: swSysError("Read from socket[%d] failed.", event->fd); return SW_OK; case SW_CLOSE: goto __close; case SW_WAIT: return SW_OK; default: return SW_OK; } } else if (n == 0) { __close: return cli->close(cli); } else { cli->onReceive(cli, buf, n); #ifdef SW_CLIENT_RECV_AGAIN if (n == buf_size) { goto recv_again; } #endif return SW_OK; } return SW_OK; }
static int swClient_onWrite(swReactor *reactor, swEvent *event) { swClient *cli = event->socket->object; swConnection *_socket = cli->socket; if (cli->socket->active) { #ifdef SW_USE_OPENSSL if (cli->open_ssl && _socket->ssl_state == SW_SSL_STATE_WAIT_STREAM) { if (swClient_ssl_handshake(cli) < 0) { goto connect_fail; } else if (_socket->ssl_state == SW_SSL_STATE_READY) { goto connect_success; } else { if (_socket->ssl_want_read) { SwooleG.main_reactor->set(SwooleG.main_reactor, event->fd, SW_FD_STREAM_CLIENT | SW_EVENT_READ); } return SW_OK; } } #endif if (swReactor_onWrite(SwooleG.main_reactor, event) < 0) { return SW_ERR; } if (cli->onBufferEmpty && _socket->high_watermark && _socket->out_buffer->length <= cli->buffer_low_watermark) { _socket->high_watermark = 0; cli->onBufferEmpty(cli); } return SW_OK; } socklen_t len = sizeof(SwooleG.error); if (getsockopt(event->fd, SOL_SOCKET, SO_ERROR, &SwooleG.error, &len) < 0) { swWarn("getsockopt(%d) failed. Error: %s[%d]", event->fd, strerror(errno), errno); return SW_ERR; } //success if (SwooleG.error == 0) { //listen read event SwooleG.main_reactor->set(SwooleG.main_reactor, event->fd, SW_FD_STREAM_CLIENT | SW_EVENT_READ); //connected _socket->active = 1; //socks5 proxy if (cli->socks5_proxy && cli->socks5_proxy->state == SW_SOCKS5_STATE_WAIT) { char buf[3]; swSocks5_pack(buf, cli->socks5_proxy->username == NULL ? 0x00 : 0x02); cli->socks5_proxy->state = SW_SOCKS5_STATE_HANDSHAKE; return cli->send(cli, buf, sizeof(buf), 0); } #ifdef SW_USE_OPENSSL if (cli->open_ssl) { if (swClient_enable_ssl_encrypt(cli) < 0) { goto connect_fail; } if (swClient_ssl_handshake(cli) < 0) { goto connect_fail; } else { _socket->ssl_state = SW_SSL_STATE_WAIT_STREAM; } return SW_OK; } connect_success: #endif if (cli->onConnect) { cli->onConnect(cli); } } else { #ifdef SW_USE_OPENSSL connect_fail: #endif cli->close(cli); if (cli->onError) { cli->onError(cli); } } return SW_OK; }
static int swClient_tcp_connect_sync(swClient *cli, char *host, int port, double timeout, int nonblock) { int ret, n; char buf[1024]; cli->timeout = timeout; if (swClient_inet_addr(cli, host, port) < 0) { return SW_ERR; } if (nonblock == 1) { swSetNonBlock(cli->socket->fd); } else { if (cli->timeout > 0) { swSocket_set_timeout(cli->socket->fd, timeout); } swSetBlock(cli->socket->fd); } while (1) { ret = connect(cli->socket->fd, (struct sockaddr *) &cli->server_addr.addr, cli->server_addr.len); if (ret < 0) { if (errno == EINTR) { continue; } } break; } if (ret >= 0) { cli->socket->active = 1; //socks5 proxy if (cli->socks5_proxy) { swSocks5_pack(buf, cli->socks5_proxy->username == NULL ? 0x00 : 0x02); if (cli->send(cli, buf, 3, 0) < 0) { return SW_ERR; } cli->socks5_proxy->state = SW_SOCKS5_STATE_HANDSHAKE; while (1) { n = cli->recv(cli, buf, sizeof(buf), 0); if (n > 0) { if (swSocks5_connect(cli, buf, n) < 0) { return SW_ERR; } else { if (cli->socks5_proxy->state == SW_SOCKS5_STATE_READY) { break; } else { continue; } } } return SW_ERR; } } #ifdef SW_USE_OPENSSL if (cli->open_ssl) { if (swClient_enable_ssl_encrypt(cli) < 0) { return SW_ERR; } if (swClient_ssl_handshake(cli) < 0) { return SW_ERR; } } #endif } return ret; }