/* **============================================================================== ** ** Open Management Infrastructure (OMI) ** ** Copyright (c) Microsoft Corporation ** ** Licensed under the Apache License, Version 2.0 (the "License"); you may not ** use this file except in compliance with the License. You may obtain a copy ** of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, ** MERCHANTABLITY OR NON-INFRINGEMENT. ** ** See the Apache 2 License for the specific language governing permissions ** and limitations under the License. ** **============================================================================== */ #include "utils.h" #include #include #include #include #include #if defined(CONFIG_OS_WINDOWS) #include #else #include #include static pid_t child; #endif using namespace std; #define REQUEST_HEADER_FMT \ "POST /wsman HTTP/1.1\r\n" \ "Content-Length: %d\r\n"\ "Connection: Keep-Alive\r\n"\ "Content-Type: application/soap+xml;charset=UTF-8\r\n"\ "Authorization: Basic \t \tcm9vdDpPcHNNZ3IyMDA3UjI=\t \r\n"\ "\r\n" #define REQUEST_HEADER_FMT_UTF16 \ "POST /wsman HTTP/1.1\r\n" \ "Content-Length: %d\r\n"\ "Connection: Keep-Alive\r\n"\ "Content-Type: application/soap+xml;charset=UTF-16\r\n"\ "Authorization: Basic \t \tcm9vdDpPcHNNZ3IyMDA3UjI=\t \r\n"\ "\r\n" #define REQUEST_HEADER_MAX_SIZE sizeof(REQUEST_HEADER_FMT_UTF16) Sock SockConnectLocal(unsigned short port) { Sock sock; Addr addr; MI_Result r; Sock_Start(); // Initialize address (connect using loopback). r = Addr_Init(&addr, "127.0.0.1", port); UT_ASSERT(r == MI_RESULT_OK); // Create client socket. r = Sock_Create(&sock); UT_ASSERT(r == MI_RESULT_OK); r = Sock_Connect(sock, &addr); UT_ASSERT(r == MI_RESULT_OK); return sock; } void SockSendRecvHTTP( Sock s, bool useUtf16HeaderAttribute, const string& request_body, string& response_header, string& response_body) { // prepare data to send char currentLine[REQUEST_HEADER_MAX_SIZE + 10 /* content length */ ]; size_t buf_size, sent = 0; MI_Result r; buf_size = (size_t)Snprintf( currentLine, sizeof(currentLine), (useUtf16HeaderAttribute ? REQUEST_HEADER_FMT_UTF16 : REQUEST_HEADER_FMT), (int)request_body.size() ); r = Sock_Write(s, currentLine, buf_size, &sent); UT_ASSERT (MI_RESULT_OK == r); UT_ASSERT (sent == buf_size); // body (if present) if (!request_body.empty()) { sent = 0; r = Sock_Write(s, request_body.c_str(), request_body.size(), &sent); UT_ASSERT (MI_RESULT_OK == r); UT_ASSERT (sent == request_body.size()); } // read resonse response_header.resize(16 * 1024); size_t read = 0, buf_read = 0; string::size_type pos_crcr; for (;;) { r = Sock_Read(s, &response_header[0], response_header.size() - buf_read, &read); UT_ASSERT (MI_RESULT_OK == r); buf_read += read; pos_crcr = response_header.find("\r\n\r\n"); if (string::npos != pos_crcr) { response_header.resize(buf_read); break; } } response_body = response_header.substr(pos_crcr + 4); response_header = response_header.substr(0, pos_crcr); const char CONTENT_LEN[] = "Content-Length:"; string::size_type pos_cl = response_header.find(CONTENT_LEN); size_t contentLength = 0; if (string::npos != pos_cl) { contentLength = atol(response_header.c_str() + pos_cl + sizeof(CONTENT_LEN)-1); } //cout << "cl: " << contentLength << endl; //cout << "resp header: " << response_header << endl << endl << "body: " << response_body << endl; while (response_body.size() < contentLength) { size_t old_size = response_body.size(); response_body.resize(contentLength); r = Sock_Read(s, &response_body[0] + old_size, contentLength - old_size, &read); UT_ASSERT (MI_RESULT_OK == r); response_body.resize(old_size + read); } //cout << "resp header: " << response_header << endl << endl << "body: " << response_body << endl; } /* launching and terminating the server */ void StartServerAndConnect( bool ignoreAuth, ProtocolCallback callback, Protocol** protocol) { MI_Result r; const char* path = GetPath(ID_SERVERPROGRAM); char http[32]; char https[32]; string socketFile = GetPath(ID_SOCKETFILE); Snprintf(http, sizeof(http),"%d", ut::getUnittestPortNumberWSMANHTTP()); Snprintf(https, sizeof(https),"%d", ut::getUnittestPortNumberWSMANHTTPS()); std::string v; if (!ut::testGetAttr("skipServer", v)) { #if defined(CONFIG_OS_WINDOWS) MI_UNUSED(ignoreAuth); intptr_t res = _spawnl(_P_NOWAIT, path, path, "--stopnoop", "--rundir", GetPath(ID_PREFIX), "--httpport", http, "--httpsport", https, "--livetime", "300", NULL); res = res; #else child = fork(); if (!child) { execl(path, path, "--stopnoop", ignoreAuth ? "--ignoreAuthentication" : "--stopnoop", "--rundir", GetPath(ID_PREFIX), "--httpport", http, "--httpsport", https, "--socketfile", socketFile.c_str(), "--livetime", "300", NULL ); exit(1); // never get here } #endif } // wait for server to start // trying to connect in a loop: // since connect may fail quickly if server is not running // keep doing it in a loop int attempt; for ( attempt = 0; attempt < 400; attempt++ ) { mi::Client cl; const MI_Uint64 TIMEOUT = 1 * 1000 * 1000; #if defined(CONFIG_OS_WINDOWS) if (cl.Connect(MI_T("7777"), MI_T("unittest"), MI_T("unittest"), TIMEOUT)) #else if (cl.Connect(socketFile.c_str(), MI_T(USER), MI_T(PASSWORD), TIMEOUT)) #endif break; ut::sleep_ms(10); } if ( attempt == 400 ) { std::cout << "Warning: unable to connect to the server!\n"; } r = Protocol_New_Connector(protocol, 0, socketFile.c_str(), callback, 0, 0, 0, USER, PASSWORD); } void StopServerAndDisconnect( Protocol** protocol) { NoOpReq* rqt; std::string v; if (ut::testGetAttr("skipServer", v)) { Protocol_Delete(*protocol); *protocol = 0; return ; } rqt = NoOpReq_New(0); if (rqt) { Protocol_Send(*protocol, &rqt->base); NoOpReq_Release(rqt); } Protocol_Run(*protocol, 10000); Protocol_Delete(*protocol); *protocol = 0; #if !defined(CONFIG_OS_WINDOWS) int attempt = 0; do { usleep(20000); attempt++; if (attempt > 100 ) { cout << "Warning: unable to stop the server!\n"; break; } } while( child != waitpid(child, 0, WNOHANG)); #endif }