1 mike 1.1 /*
2 **==============================================================================
3 **
4 ** Open Management Infrastructure (OMI)
5 **
6 ** Copyright (c) Microsoft Corporation
7 **
8 ** Licensed under the Apache License, Version 2.0 (the "License"); you may not
9 ** use this file except in compliance with the License. You may obtain a copy
10 ** of the License at
11 **
12 ** http://www.apache.org/licenses/LICENSE-2.0
13 **
14 ** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 ** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
16 ** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
17 ** MERCHANTABLITY OR NON-INFRINGEMENT.
18 **
19 ** See the Apache 2 License for the specific language governing permissions
20 ** and limitations under the License.
21 **
22 mike 1.1 **==============================================================================
23 */
24
25 #include "utils.h"
26 #include <ut/ut.h>
27 #include <base/io.h>
28 #include <base/paths.h>
29 #include <omiclient/client.h>
30 #include <iostream>
31
32 #if defined(CONFIG_OS_WINDOWS)
33 #include <process.h>
34 #else
35 #include <unistd.h>
36 #include <sys/wait.h>
37
38 static pid_t child;
39 #endif
40
41 using namespace std;
42
43 mike 1.1 #define REQUEST_HEADER_FMT \
44 "POST /wsman HTTP/1.1\r\n" \
45 "Content-Length: %d\r\n"\
46 "Connection: Keep-Alive\r\n"\
47 "Content-Type: application/soap+xml;charset=UTF-8\r\n"\
48 "Authorization: Basic \t \tcm9vdDpPcHNNZ3IyMDA3UjI=\t \r\n"\
49 "\r\n"
50
51 #define REQUEST_HEADER_FMT_UTF16 \
52 "POST /wsman HTTP/1.1\r\n" \
53 "Content-Length: %d\r\n"\
54 "Connection: Keep-Alive\r\n"\
55 "Content-Type: application/soap+xml;charset=UTF-16\r\n"\
56 "Authorization: Basic \t \tcm9vdDpPcHNNZ3IyMDA3UjI=\t \r\n"\
57 "\r\n"
58
59 #define REQUEST_HEADER_MAX_SIZE sizeof(REQUEST_HEADER_FMT_UTF16)
60
61 Sock SockConnectLocal(unsigned short port)
62 {
63 Sock sock;
64 mike 1.1 Addr addr;
65 MI_Result r;
66
67 Sock_Start();
68
69 // Initialize address (connect using loopback).
70 r = Addr_Init(&addr, "127.0.0.1", port);
71 UT_ASSERT(r == MI_RESULT_OK);
72
73 // Create client socket.
74 r = Sock_Create(&sock);
75 UT_ASSERT(r == MI_RESULT_OK);
76
77 r = Sock_Connect(sock, &addr);
78 UT_ASSERT(r == MI_RESULT_OK);
79 return sock;
80 }
81
82 void SockSendRecvHTTP(
83 Sock s,
84 bool useUtf16HeaderAttribute,
85 mike 1.1 const string& request_body,
86 string& response_header,
87 string& response_body)
88 {
89 // prepare data to send
90
91 char currentLine[REQUEST_HEADER_MAX_SIZE + 10 /* content length */ ];
92
93 size_t buf_size, sent = 0;
94 MI_Result r;
95
96 buf_size = (size_t)Snprintf(
97 currentLine,
98 sizeof(currentLine),
99 (useUtf16HeaderAttribute ? REQUEST_HEADER_FMT_UTF16 : REQUEST_HEADER_FMT),
100 (int)request_body.size() );
101
102 r = Sock_Write(s, currentLine, buf_size, &sent);
103 UT_ASSERT (MI_RESULT_OK == r);
104 UT_ASSERT (sent == buf_size);
105
106 mike 1.1 // body (if present)
107 if (!request_body.empty())
108 {
109 sent = 0;
110 r = Sock_Write(s, request_body.c_str(), request_body.size(), &sent);
111
112 UT_ASSERT (MI_RESULT_OK == r);
113 UT_ASSERT (sent == request_body.size());
114 }
115
116 // read resonse
117
118 response_header.resize(16 * 1024);
119 size_t read = 0, buf_read = 0;
120 string::size_type pos_crcr;
121
122 for (;;)
123 {
124 r = Sock_Read(s, &response_header[0], response_header.size() - buf_read, &read);
125 UT_ASSERT (MI_RESULT_OK == r);
126
127 mike 1.1 buf_read += read;
128
129 pos_crcr = response_header.find("\r\n\r\n");
130
131 if (string::npos != pos_crcr)
132 {
133 response_header.resize(buf_read);
134 break;
135 }
136 }
137
138 response_body = response_header.substr(pos_crcr + 4);
139 response_header = response_header.substr(0, pos_crcr);
140
141 const char CONTENT_LEN[] = "Content-Length:";
142
143 string::size_type pos_cl = response_header.find(CONTENT_LEN);
144 size_t contentLength = 0;
145
146 if (string::npos != pos_cl)
147 {
148 mike 1.1 contentLength = atol(response_header.c_str() + pos_cl + sizeof(CONTENT_LEN)-1);
149 }
150 //cout << "cl: " << contentLength << endl;
151 //cout << "resp header: " << response_header << endl << endl << "body: " << response_body << endl;
152
153 while (response_body.size() < contentLength)
154 {
155 size_t old_size = response_body.size();
156 response_body.resize(contentLength);
157
158 r = Sock_Read(s, &response_body[0] + old_size, contentLength - old_size, &read);
159 UT_ASSERT (MI_RESULT_OK == r);
160
161 response_body.resize(old_size + read);
162 }
163 //cout << "resp header: " << response_header << endl << endl << "body: " << response_body << endl;
164 }
165
166
167
168 /* launching and terminating the server */
169 mike 1.1 void StartServerAndConnect(
170 bool ignoreAuth,
171 ProtocolCallback callback,
172 Protocol** protocol)
173 {
174 MI_Result r;
175 const char* path = GetPath(ID_SERVERPROGRAM);
176 char http[32];
177 char https[32];
178 string socketFile = GetPath(ID_SOCKETFILE);
179
180 Snprintf(http, sizeof(http),"%d", ut::getUnittestPortNumberWSMANHTTP());
181 Snprintf(https, sizeof(https),"%d", ut::getUnittestPortNumberWSMANHTTPS());
182
183 std::string v;
184
185 if (!ut::testGetAttr("skipServer", v))
186 {
187
188 #if defined(CONFIG_OS_WINDOWS)
189 MI_UNUSED(ignoreAuth);
190 mike 1.1
191 intptr_t res = _spawnl(_P_NOWAIT, path, path, "--stopnoop", "--rundir",
192 GetPath(ID_PREFIX),
193 "--httpport", http,
194 "--httpsport", https,
195 "--livetime", "300",
196 NULL);
197 res = res;
198 #else
199 child = fork();
200 if (!child)
201 {
202 execl(path, path, "--stopnoop",
203 ignoreAuth ? "--ignoreAuthentication" : "--stopnoop",
204 "--rundir", GetPath(ID_PREFIX),
205 "--httpport", http,
206 "--httpsport", https,
207 "--socketfile", socketFile.c_str(),
208 "--livetime", "300",
209 NULL );
210 exit(1); // never get here
211 mike 1.1 }
212 #endif
213 }
214
215
216 // wait for server to start
217 // trying to connect in a loop:
218 // since connect may fail quickly if server is not running
219 // keep doing it in a loop
220 int attempt;
221
222 for ( attempt = 0; attempt < 400; attempt++ )
223 {
224 mi::Client cl;
225 const MI_Uint64 TIMEOUT = 1 * 1000 * 1000;
226
227 #if defined(CONFIG_OS_WINDOWS)
228 if (cl.Connect(MI_T("7777"), MI_T("unittest"), MI_T("unittest"), TIMEOUT))
229 #else
230 if (cl.Connect(socketFile.c_str(), MI_T(USER), MI_T(PASSWORD), TIMEOUT))
231 #endif
232 mike 1.1 break;
233
234 ut::sleep_ms(10);
235 }
236
237 if ( attempt == 400 )
238 {
239 std::cout << "Warning: unable to connect to the server!\n";
240 }
241 r = Protocol_New_Connector(protocol, 0, socketFile.c_str(), callback, 0,
242 0, 0, USER, PASSWORD);
243 }
244
245
246
247 void StopServerAndDisconnect(
248 Protocol** protocol)
249 {
250 NoOpReq* rqt;
251 std::string v;
252
253 mike 1.1 if (ut::testGetAttr("skipServer", v))
254 {
255 Protocol_Delete(*protocol);
256 *protocol = 0;
257 return ;
258 }
259
260 rqt = NoOpReq_New(0);
261 if (rqt)
262 {
263 Protocol_Send(*protocol, &rqt->base);
264 NoOpReq_Release(rqt);
265 }
266 Protocol_Run(*protocol, 10000);
267
268 Protocol_Delete(*protocol);
269 *protocol = 0;
270
271 #if !defined(CONFIG_OS_WINDOWS)
272 int attempt = 0;
273 do {
274 mike 1.1 usleep(20000);
275 attempt++;
276
277 if (attempt > 100 )
278 {
279 cout << "Warning: unable to stop the server!\n";
280 break;
281 }
282 }
283 while( child != waitpid(child, 0, WNOHANG));
284 #endif
285 }
|