httpClient.c
6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#include "httpClient.h"
/*
------------
PUT /path/file.html HTTP/1.1
Host: www.host1.com:80
Content-Type: application/json; charset=UTF-8
[json file]
-----------
*/
int httpRequest(struct httpHeaders head, char* content, int content_size)
{
struct netconn *neocon = NULL;
struct ip_addr remote_ip;
struct netbuf *netBufs;
char* request;
char* response;
err_t connection_ok = -1;
ip4_addr_set_u32(&remote_ip,ipaddr_addr(SERVER_IP));
// Check or default params
printf("httpRequest: Checking params\r\n");
if (head.uri == NULL || head.host == NULL)
{
return 1;
}
// Calculate header size
printf("httpRequest: Calculating header size\r\n");
int head_size = strlen(reqMethod2text(head.method));
head_size += strlen(" ") + head.uri_size + strlen(" HTTP/1.1") + strlen(ENDL);
head_size += strlen("Host: ") + head.host_size + strlen(ENDL);
//if (remote_port != '0') head_size += sizeof ":" + 2*sizeof(char);
if(content_size > 0)
{
head_size += strlen(CONTENT_TYPE_HEADER) + strlen(ENDL);
head_size += strlen("Content-Length: ") + numberofdigits(content_size) + 2*(strlen(ENDL));
}
// Build request head
printf("httpRequest: Building request head\r\n");
int request_size = head_size + content_size + 2*(strlen(ENDL));
request = (char *) chHeapAlloc(NULL,request_size);
strcpy(request, reqMethod2text(head.method));
strcat(request, " ");
strcat(request, head.uri);
strcat(request, " HTTP/1.1\r\n");
strcat(request, "Host: ");
strcat(request, head.host);
//if (remote_port != '0'){ strcat(request, ":"); strcat(request, remote_port); }
strcat(request, ENDL);
if(content_size > 0)
{
strcat(request, CONTENT_TYPE_HEADER);
strcat(request, ENDL);
}
strcat(request, "Content-Length: ");
char *str_content_size = int2string(content_size);
strcat(request, str_content_size);
chHeapFree(str_content_size);
// Interlude
strcat(request, ENDL);
strcat(request, ENDL);
// Build request with content
if(content_size > 0)
{
printf("httpRequest: Adding content to request string\r\n");
strcat(request, content);
}
else
{
printf("httpRequest: Skipping void content\r\n");
}
printf("packet: %s\r\n",request);
// Set connection
while(connection_ok !=0) // != ERR_OK
{
printf("httpRequest: Setting connection\r\n");
neocon = netconn_new(NETCONN_TCP);
if(neocon == NULL)
{
printf("\\->Socket creation FAILED. Have you called liwb\r\n");
}
/*local_ip.addr = 0;//getip
netconn_bind(neocon, IP_ADDR_ANY, LOCAL_PORT); //88 is provisional local port.*/
printf("httpRequest: Establishing connection\r\n");
netconn_connect(neocon, &remote_ip, DEFAULT_REMOTE_PORT);
// Send Request
printf("httpRequest: Sending request\r\n");
err_t err=netconn_write(neocon, request, request_size, NETCONN_NOCOPY);
printf("res write= %d\r\n",err);
chHeapFree(request);
// Wait for Response
printf("httpRequest: Waiting for response\r\n");
//neocon->recv_timeout = 5000; // for 5s
connection_ok = netconn_recv(neocon, &netBufs);
printf("res recv= %d\r\n",connection_ok);
if(connection_ok !=0)
{
netbuf_delete(netBufs);
netconn_close(neocon);
netconn_delete(neocon);
}
}
// Manage Response
printf("httpRequest: Response received. Let's parse the information\r\n");
response = (char*)chHeapAlloc(NULL,4*sizeof(char));
netbuf_copy_partial(netBufs,response,3,9); // read 3B starting from 9th -> read response code. "HTTP/1.1 301 Moved Permanently"
printf("httpRequest: Unbelievablelybilbiyblyib successful! :D\r\nResponse code: %s\r\n",response);
int http_response = response2int(response);
// alliberem Mandela i Willy
netbuf_delete(netBufs);
netconn_close(neocon);
netconn_delete(neocon);
chHeapFree(response);
return http_response;
}
/*
err_t netconn_write ( struct netconn * aNetConn, const void * aData, size_t aSize, u8_t aApiFlags );
aNetConn : the netconn object the data is written to
aData : address of beginning of the data to write
aSize : the length of the data in bytes
aApiFlags : either of
NETCONN_NOCOPY if the data is stable for the time of the transmission (static data or heap)
NETCONN_COPY if the data is not stable for the time of the transmission (stack)
With the netconn API, netconn_recv() returns a netbuf which may contain a chain of pbufs. You have no control over how much data will be returned in a single request, which may be more or less than you want to deal with. You can use various netbuf functions to copy data out of the buffer. If you need more data, you must call netconn_recv() again to get the next netbuf. If you received more data than you wanted, you will have to manage the extra data yourself.
u16_t netbuf_copy_partial ( struct netbuf * aNetBuf, void * aData, u16_t aLen, u16_t aOffset );
Copy at most "aLen" bytes from the netbuf object to the destination location. The second alternative can start at an offset instead of 0.
in aNetBuf : netbuf object the data is copied from
out aData : address of the memory where the data is copied to
in aLen : the size of the buffer, or the length of data to copy
in aOffset : an offset to start the with copy operation. In "netbuf_copy" this value is 0
return : total number of copied bytes, might be 0
Contray to using "netbuf_data" you don't have to fumble around with chained buffers. You get all the data out of the buffer. As a drawback you have an extra overhead of memory usage.
*/
const char* reqMethod2text(enum reqMethod method)
{
switch(method)
{
case post:
return "POST";
case put:
return "PUT";
case get:
return "GET";
case del:
return "DELETE";
default:
return NULL;
}
}
char* int2string(int num)
{
char* manders;
manders = (char*)chHeapAlloc(NULL,numberofdigits(num)+1);
sprintf(manders, "%d", num);
return manders;
}
int numberofdigits(int number) // 0 has one digit.
{
int digits = 0;
while (number)
{
number /= 10;
digits++;
}
return (digits == 0 ? 1 : digits);
}
int response2int(char* chars) //int atoi (char[]) fa el mateix xD
{
return ( (chars[0]-'0')*100 + (chars[1]-'0')*10 + (chars[2]-'0')*1 );
}