String ZMQPollData::createKey(const Variant& val) { if (val.isResource()) { char tmp[35]; int tmpLen = snprintf(tmp, 35, "r:%d", val.asCResRef().toInt32()); return String(tmp, tmpLen, CopyString); } else { assert(val.isObject()); return HHVM_FN(spl_object_hash)(val.asCObjRef()); } }
void TestFastCGIServer::WaitForOpenPort(const char* host, int port) { for (int i = 0; i < 100; ++i) { Variant result = f_fsockopen(host, port); if (result.isResource()) { f_socket_close(result.asCResRef()); return; } usleep(100000); // 100 ms } throw std::runtime_error("Waiting for open port failed!"); }
bool f_stream_is_local(const Variant& stream_or_url) { if (stream_or_url.isString()) { auto wrapper = Stream::getWrapperFromURI(stream_or_url.asCStrRef()); return wrapper->m_isLocal; } else if (stream_or_url.isResource()) { File* file = dynamic_cast<File*>(stream_or_url.asCResRef().get()); if (!file) { raise_warning("supplied resource is not a valid stream resource"); return false; } return file->m_isLocal; } // Zend returns true for random data types... return true; }
void TestFastCGIServer::StopServer() { TestMessageExchange mx; CHECK(LoadExchangeFromJson(std::string("test/ext/fastcgi/admin_stop.json"), mx, __FILE__,__LINE__)); Variant socket; Variant admin_socket; for (int i = 0; i < 10; i++) { Variant tcp_proto = f_getprotobyname(String("tcp")); if (socket.isResource()) { f_socket_close(socket.asCResRef()); socket = false; } if (admin_socket.isResource()) { f_socket_close(admin_socket.asCResRef()); admin_socket = false; } if (!tcp_proto.isInteger()) { printf("Invalid return value from getprotobyname"); continue; } else { socket = f_socket_create(AF_INET, SOCK_STREAM, tcp_proto.toInt32()); } if (!socket.isResource()) { printf("Unable to initialize a socket\n"); continue; } else if (!f_socket_connect(socket.asCResRef(), "localhost", m_adminPort)) { printf("Unable to connect to admin server.\n"); continue; } for (auto it = mx.m_messages.begin(); it != mx.m_messages.end(); ++it) { CHECK(it->m_command == TestMessage::Command::SEND); int len = it->m_body.size(); String body_buffer = String( reinterpret_cast<const char*>(it->m_body.data()), len, CopyString); Variant sent_len = f_socket_send(socket.asCResRef(), body_buffer, body_buffer.size(), 0); if (!sent_len.isInteger()) { printf("Error while sending payload\n"); continue; } else if (sent_len.toInt32() < len) { printf("Data truncated while sending\n"); printf("Sent length: %d, expected: %d\n", sent_len.toInt32(), (int) len); continue; } printf("Successfully sent a message\n"); } WaitForClosedPort("127.0.0.1", m_adminPort); WaitForClosedPort("127.0.0.1", m_serverPort); usleep(500000); // To be sure. admin_socket = f_socket_create(AF_INET, SOCK_STREAM, tcp_proto.toInt32()); if (!admin_socket.isResource()) { printf("Unable to initialize a socket\n"); continue; } if (!f_socket_connect(admin_socket.asCResRef(), "localhost", m_serverPort)) { break; } } if (socket.isResource()) { f_socket_close(socket.asCResRef()); } if (admin_socket.isResource()) { f_socket_close(admin_socket.asCResRef()); } }
bool TestFastCGIServer::VerifyExchange(const TestMessageExchange& mx, int reps, const char* file, int line) { Variant cwd = f_getcwd(); CHECK(cwd.isString()); CHECK(!mx.m_messages.empty()); if (!CleanUp()) { return false; } bool result = true; for (int i = 0; i < reps; ++i) { AsyncFunc<TestFastCGIServer> func(this, &TestFastCGIServer::RunServer); func.start(); WaitForOpenPort("127.0.0.1", m_adminPort); WaitForOpenPort("127.0.0.1", m_serverPort); Variant tcp_proto = f_getprotobyname(String("tcp")); TestMessageExchange mx2 = mx; if (i > 0) { mx2 = mx2.aggregate().split(); } Variant socket; if (!tcp_proto.isInteger()) { printf("Invalid return value from getprotobyname"); result = false; } else { socket = f_socket_create(AF_INET, SOCK_STREAM, tcp_proto.toInt32()); } if (!socket.isResource()) { printf("Unable to initialize a socket\n"); result = false; } else if (!f_socket_connect(socket.asCResRef(), "localhost", m_serverPort)) { printf("Unable to connect to server.\n"); result = false; } for (auto it = mx2.m_messages.begin(); result && it != mx2.m_messages.end(); ++it) { int len = it->m_body.size(); CHECK(it->m_body.size() == it->m_mask.size()); switch (it->m_command) { case TestMessage::Command::SEND: { printf("Sending a message, length=%d\n", len); String body_buffer = String( reinterpret_cast<const char*>(it->m_body.data()), len, CopyString); Variant sent_len = f_socket_send(socket.asCResRef(), body_buffer, len, 0); int usecs = rand() % 50000; usleep(usecs); // Waiting on Nade's algorithm if (!sent_len.isInteger()) { printf("Error while sending payload\n"); result = false; } else if (sent_len.toInt32() < len) { printf("Data truncated while sending\n"); printf("Sent length: %d, expected: %d\n", sent_len.toInt32(), (int) len); result = false; } else { printf("Successfully sent a message\n"); CHECK(sent_len.toInt32() == len); } break; } case TestMessage::Command::RECV: { printf("Receiving a message\n"); VRefParamValue actual_body; Variant recv_len = f_socket_recv(socket.asCResRef(), actual_body, len, 0); if (!recv_len.isInteger()) { printf("Error while receiving payload\n"); result = false; } else if (recv_len.toInt32() < len) { printf("Too little data received\n"); result = false; } else { CHECK(recv_len.toInt32() == len); CHECK(actual_body.isString()); for (int i = 0; i < len; ++i) { if ((actual_body.toString()[i] & it->m_mask[i]) != (it->m_body[i] & it->m_mask[i])) { printf("Received payload mismatch at offset: %d " "actual value: %02x, expected: %02x, " "mask was: %02x\n", i, actual_body.toString()[i] & it->m_mask[i], it->m_body[i] & it->m_mask[i], it->m_mask[i]); result = false; } } printf("Successfully read a message\n"); } break; } case TestMessage::Command::CLOSE: { break; } case TestMessage::Command::RECV_CLOSE: { VRefParamValue actual_body; Variant recv_len = f_socket_recv(socket.asResRef(), actual_body, 1, 0); if (recv_len.isInteger()) { printf("Connection not closed by the remote side\n"); result = false; } break; } default: printf("Invalid message command\n"); result = false; } } if (socket.isResource()) { f_socket_close(socket.asCResRef()); socket = false; } AsyncFunc<TestFastCGIServer>(this, &TestFastCGIServer::StopServer).run(); func.waitForEnd(); } return result; }