2 * This file is part of INAV Project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
6 * You can obtain one at http://mozilla.org/MPL/2.0/.
8 * Alternatively, the contents of this file may be used under the terms
9 * of the GNU General Public License Version 3, as described below:
11 * This file is free software: you may copy, redistribute and/or modify
12 * it under the terms of the GNU General Public License as published by the
13 * Free Software Foundation, either version 3 of the License, or (at your
14 * option) any later version.
16 * This file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19 * Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see http://www.gnu.org/licenses/.
33 #include <sys/socket.h>
34 # include <netinet/in.h>
37 #include <sys/select.h>
39 #include "simple_soap_client.h"
41 #define REC_BUF_SIZE 6000
42 char recBuffer
[REC_BUF_SIZE
];
44 bool soapClientConnect(soap_client_t
*client
, const char *address
, int port
)
46 client
->sockedFd
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
);
47 if (client
->sockedFd
< 0) {
52 if (setsockopt(client
->sockedFd
, SOL_SOCKET
, SO_REUSEADDR
, &one
, sizeof(one
)) < 0) {
56 client
->socketAddr
.sin_family
= AF_INET
;
57 client
->socketAddr
.sin_port
= htons(port
);
58 client
->socketAddr
.sin_addr
.s_addr
= inet_addr(address
);
60 if (connect(client
->sockedFd
, (struct sockaddr
*)&client
->socketAddr
, sizeof(client
->socketAddr
)) < 0) {
64 client
->isConnected
= true;
65 client
->isInitalised
= true;
70 void soapClientClose(soap_client_t
*client
)
72 close(client
->sockedFd
);
73 memset(client
, 0, sizeof(soap_client_t
));
74 client
->isConnected
= false;
75 client
->isInitalised
= false;
78 void soapClientSendRequestVa(soap_client_t
*client
, const char* action
, const char *fmt
, va_list va
)
80 if (!client
->isConnected
) {
85 if (vasprintf(&requestBody
, fmt
, va
) < 0) {
90 if (asprintf(&request
, "POST / HTTP/1.1\r\nsoapaction: %s\r\ncontent-length: %u\r\ncontent-type: text/xml;charset='UTF-8'\r\nConnection: Keep-Alive\r\n\r\n<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body>%s</soap:Body></soap:Envelope>",
91 action
, (unsigned)strlen(requestBody
), requestBody
) < 0) {
95 send(client
->sockedFd
, request
, strlen(request
), 0);
101 void soapClientSendRequest(soap_client_t
*client
, const char* action
, const char *fmt
, ...)
106 soapClientSendRequestVa(client
, action
, fmt
, va
);
110 static bool soapClientPoll(soap_client_t
*client
, uint32_t timeout_ms
)
116 FD_SET(client
->sockedFd
, &fds
);
118 tv
.tv_sec
= timeout_ms
/ 1000;
119 tv
.tv_usec
= (timeout_ms
% 1000) * 1000UL;
121 if (select(client
->sockedFd
+ 1, &fds
, NULL
, NULL
, &tv
) != 1) {
128 char* soapClientReceive(soap_client_t
*client
)
130 if (!client
->isInitalised
){
134 if (!soapClientPoll(client
, 1000)) {
138 ssize_t size
= recv(client
->sockedFd
, recBuffer
, REC_BUF_SIZE
, 0);
144 char* pos
= strstr(recBuffer
, "Content-Length: ");
149 uint32_t contentLength
= strtoul(pos
+ 16, NULL
, 10);
150 char *body
= strstr(pos
, "\r\n\r\n");
157 ssize_t expectedLength
= contentLength
+ body
- recBuffer
;
158 if ((unsigned)expectedLength
>= sizeof(recBuffer
)) {
162 while (size
< expectedLength
){
163 ssize_t size2
= recv(client
->sockedFd
, &recBuffer
[size
], sizeof(recBuffer
- size
+ 1), 0);
170 recBuffer
[size
] = '\0';