extern int decode(char *filename,int type){ return type ? decode0(filename) : decode1(filename); }
bool ws::connect(short port) { if(!socklib::connect(port)) return false; size_t pos = 4; string sb = recv(); while(string::npos== sb.find("\r\n\r\n")) sb += recv(); try { //read GET header if(' TEG'!= *(const long*)sb.data()) throw ws::exception("Not a GET request"); string path = consume(sb, pos, " "); string httpVer = consume(sb, pos); //read header-lines map<string, string> hdrs; string hl, hn; size_t hv; while(""!= (hl = consume(sb, pos))) { hv = 0; hn = consume(hl, hv, ": "); hdrs[hn] = hl.substr(hv); } if( "Upgrade"!= hdrs["Connection"] || "WebSocket"!= hdrs["Upgrade"]) throw ws::exception("Not a WebSocket request"); map<string, string>::iterator i, e = hdrs.end(); version = (e!= (i= hdrs.find("Sec-WebSocket-Version"))) ? stoi(i->second) : 0; if(0< version) throw ws::exception("Unsupported version"); //TODO: later versions while(sb.size()-pos < overload[version]) sb += recv(); stringstream out; bool secure = false; //TODO: read 'secure' flag short dftPort = secure?443:80; out << "HTTP/1.1 101 ExorCyber\r\n" << "Upgrade: WebSocket\r\n" << "Connection: Upgrade\r\n" << "Sec-WebSocket-Origin: " << hdrs["Origin"] << "\r\n" << "Sec-WebSocket-Location: ws" << (secure?"s":"") << "://" << hdrs["Host"]/*; if(port!=dftPort) out << ':' << port; out */ << path << "\r\n"; if(e!= (i= hdrs.find("Sec-WebSocket-Protocol"))) out << "Sec-WebSocket-Protocol: " << i->second << "\r\n"; switch(version) { case 0: ulong k[4] = { htonl(decode0(hdrs["Sec-WebSocket-Key1"])), htonl(decode0(hdrs["Sec-WebSocket-Key2"])) }; const ulong* clntK = (const ulong*)(sb.data()+pos); /*This gives "n`9eBk9z$R8pOtVb" ulong k[4] = { htonl(decode0("3e6b263 4 17 80")), htonl(decode0("17 9 G`ZD9 2 2b 7X 3 /r90")) }; const ulong* clntK = (const ulong*)("WjN}|M(6");*/ k[2] = clntK[0]; k[3] = clntK[1]; MD5 md5; md5.update((const char*)k, 16); md5.finalize(); out << "\r\n" << string((char*)md5.digest, 16); break; } send(out.str()); } catch(ws::exception x) { //TODO: send back 5xx clear(); debug::log("\nBad request : %s", x.what()); return false; } return true; }