Hi Mike, Thanks for helping me. Here is the code that calculates the response and do the parsing in look for the handshake. It is still pretty primitive but I wanted to get it to work first, at least for chrome, and then I would try to cover more cases.
static bool decodeHttpMessage (char * inputMessage, char * outputMessage, uint32_t *outputLength) { volatile const char str1[98] = "HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "; volatile const char s[3] = "\r\n"; volatile const char str2[5] = "\r\n\r\n"; volatile char *tokens[12]; volatile uint32_t index = 1; volatile uint32_t i; volatile char key [24]; //24 bytes volatile char magic[36] = { '2', '5', '8', 'E', 'A', 'F', 'A', '5', '-', 'E', '9', '1', '4', '-', '4', '7', 'D', 'A', '-', '9', '5', 'C', 'A', '-', 'C', '5', 'A', 'B', '0', 'D', 'C', '8', '5', 'B', '1', '1'}; volatile char sha1Input [60]; volatile char sha1Output [20]; volatile char encodedSha1 [40]; volatile uint32_t encodedLength; //Split the message into substrings to identify it tokens[0] = strtok(inputMessage, s); while( (tokens[index-1] != NULL)&& (index < 12) ) { tokens[index] = strtok(NULL, s); index ++; } //Get the key and the type of message if (strncmp(tokens[0], "GET ", 4) == 0) { for (index = 1; index < 12; index++) { if (strncmp(tokens[index], "Connection: ", 12) == 0) { if (strncmp(tokens[index] + 12, "Upgrade", 7) == 0) break; else return false; } } } else return false; //It's a websocket request for (index = 1; index < 12; index++) { if (strncmp(tokens[index], "Sec-WebSocket-Key: ", 19) == 0) { //assuming key of fixed length (that's how it is supposed to be) strncpy(key, tokens[index] + 19, 24); break; } } //Concatenate Strings for (index = 0; index < 60; index++) { if(index < 24) sha1Input[index] = key[index]; else sha1Input[index] = magic[index - 24]; } //Call to SHA function and encode mbedtls_sha1( &sha1Input[0], 60, &sha1Output[0]); //It works mbedtls_base64_encode( &encodedSha1[0], 40, &encodedLength, &sha1Output[0], 20 ); //It seems to work, it may better to calculate the encodedLength first and then allocate the encodedSha1 buffer. //Fill Output Buffer outputLength = encodedLength + 97 + 4; for (index = 0; index < outputLength ; index++) { if(index < 97) *(outputMessage + index) = str1[index]; else if ((index > 96)&& (index < 97 + encodedLength)) *(outputMessage + index) = encodedSha1[index - 97]; else *(outputMessage + index) = str2[index - 97 - encodedLength]; } //Add extra /n/r at the end return true; } I know that for example I am missing the protocols. But as I said, I will cover it later... What do you think of this and the whole implementation? On Mon, Oct 26, 2015 at 2:52 PM, Mike He <m...@amberkinetics.com> wrote: > Hi Leonardo, > > I have written a Websocket server on top of lwip, and can try to help you > directly. > > Just briefly looking at the code you posted though, a lot seems to be > missing though. Certainly, there is no way to tell if you are properly > returning a Websocket handshake given the code provided. Do you have more > detailed code that you want me to look at? > > Mike > > > > > > On 10/26/2015 10:39 AM, Leonardo Martínez wrote: > > I understand what you are saying but I don't get how is not a single entry > point: TCP_RECV is "Used to specify the function that should be called when > a TCP connection receives data". This function has to be fired when new > data comes. I can get that this process may have to be retried many times. > > You need to modify the http_parse_request function to understand the >> websocket request. Then you have to serve your response instead of the >> server's standard response with is send_headers + send_file. >> If you don't return the proper value, your data won't be sent. If you >> hog tcp buffers, your data will stop being sent and nothing else will >> work. >> Then, you have to patch other functions so next coming dara is sent to >> your websocket server and not rejected as unknown data. Essentially, >> HTTP was not conceived as a bidirectional protocol and so is the server, >> so you might find this is not easy to do. > > > That's what I thought... What do you mean with proper value? It is > supposed to be a error check before it is sent to the browser? I thought > the package was checked in the browser. I also tried to use hercules to > exchange TCP messages and it seemed to work fine. > Hog? If I close the connection, it will be hogged, right? That's what I am > suppose to do... > > decodeHttpMessage is a function I created to do the parsing of the > requests. I guess the server belongs to Atmel but I will check. > I came to this post as the base of the project is from > lwip: tcp_recv, tcp_poll, tcp_write, tcp_abort. It didn't seem that > complicated for me at first as it was a short .c file with calls to LWIP > functions... > > Thanks for your help. > > On Mon, Oct 26, 2015 at 1:51 PM, Sergio R. Caprile <scapr...@gmail.com> > wrote: > >> > - If I need to wait for a handshake in the HTTP form, it would be fine >> > if I start with a HTTP server. As I understand it, HTTP server is mostly >> > a TCP server with some retries and the particular communication scheme >> > (Get, post, etc.). >> >> No it is not >> >> A web server is a delicate piece of code [...]. >> An HTTP server is a statefull machine, and the fact that you are not >> working with sockets but with callback functions makes it even more >> complicated and cumbersome to follow. >> >> > I will take a look at your code to try to figure this out. It can be >> > something with the HS for sure. It's weird that I am doing the same that >> > they do and it doesn't work... >> >> Evidently you are not, otherwise it would work... ;^) >> >> > For me, if I get XX from http_recv it >> > should be easy to send YY back as a response. HTTP should be the next >> > step, right? >> >> You don't have a single point of entry, your application is distributed >> among many functions, you may not get the whole request at once, you >> might not be able to send the whole response at once, etc. >> >> You need to modify the http_parse_request function to understand the >> websocket request. Then you have to serve your response instead of the >> server's standard response with is send_headers + send_file. >> If you don't return the proper value, your data won't be sent. If you >> hog tcp buffers, your data will stop being sent and nothing else will >> work. >> Then, you have to patch other functions so next coming dara is sent to >> your websocket server and not rejected as unknown data. Essentially, >> HTTP was not conceived as a bidirectional protocol and so is the server, >> so you might find this is not easy to do. >> >> Your first step now should be to determine if the web server your vendor >> provided is the one in the lwIP contrib tree or it was modified by them. >> I don't see references to decodeHttpMessage() (and it doesn't follow the >> lwIP group code standard guidelines for naming convention) >> >> $ grep -R decodeHttpMessage * >> $ >> >> so my bet is that that webserver does not belong to lwIP but your vendor. >> Then, you have to choose whether: >> you'll use that webserver, in which case you should ask your >> vendor for >> help >> you'll use the contrib tree webserver, in which case you'd ask >> this >> list for help >> you'll use my fork of the contrib tree webserver, in which case >> you >> would ask me for help. If you are not in a hurry, I can try to add >> support for this to my server, but I'm quite busy right now. >> >> Regards >> >> -- >> >> >> _______________________________________________ >> lwip-users mailing list >> lwip-users@nongnu.org >> https://lists.nongnu.org/mailman/listinfo/lwip-users >> > > > > -- > Leonardo. > > > _______________________________________________ > lwip-users mailing > listlwip-users@nongnu.orghttps://lists.nongnu.org/mailman/listinfo/lwip-users > > > > _______________________________________________ > lwip-users mailing list > lwip-users@nongnu.org > https://lists.nongnu.org/mailman/listinfo/lwip-users > -- Leonardo.
_______________________________________________ lwip-users mailing list lwip-users@nongnu.org https://lists.nongnu.org/mailman/listinfo/lwip-users