void run() { WSADATA wsa; if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) { printf("Init failed"); exit(-1); } SOCKET server_fd; server_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (server_fd == INVALID_SOCKET) { printf("Invalid socket"); exit(-1); } struct sockaddr_in server_addr; int port = 56789; memset(&server_addr, 0, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(port); if (bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) { printf("Socket bind error"); exit(-1); } if (listen(server_fd, SOMAXCONN) == SOCKET_ERROR) { printf("Socket execute error"); exit(-1); } char hostname[255]; char *ip; char *local = "*"; struct hostent *hostinfo; if (gethostname(hostname, sizeof(hostname)) == 0) { if ((hostinfo = gethostbyname(hostname)) != NULL) { ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list); } else { ip = local; } } else { ip = local; } printf("Server is listening on %s:%d\n", ip, port); char doccmd[BUF_SIZE]; sprintf_s(doccmd, BUF_SIZE, "start http://%s:%d/", ip, port); //system(doccmd); while (true) { SOCKET client; struct sockaddr_in client_addr; memset(&client_addr, 0, sizeof(struct sockaddr_in)); client = accept(server_fd, (struct sockaddr*)&client_addr, 0); if (client == INVALID_SOCKET) { printf("Invalid socket"); } char request[BUF_SIZE]; char htmlfile[255]; int receive_rs = recv(client, request, sizeof(request), 0); struct req_head head = parse_request_head(request); printf("Request: %s\n", head.path); if (strcmp(head.path, "/next") == 0) { play_next(); strcpy_s(htmlfile, "html/index.html"); } else if (strcmp(head.path, "/prev") == 0) { play_prev(); strcpy_s(htmlfile, "html/index.html"); } else if (strcmp(head.path, "/play") == 0) { play(); strcpy_s(htmlfile, "html/index.html"); } else if (strcmp(head.path, "/up") == 0) { volume_up(); strcpy_s(htmlfile, "html/index.html"); } else if (strcmp(head.path, "/down") == 0) { volume_down(); strcpy_s(htmlfile, "html/index.html"); } else if (strcmp(head.path, "/mute") == 0) { mute(); strcpy_s(htmlfile, "html/index.html"); } else if (strcmp(head.path, "/shutdown") == 0) { poweroff(); strcpy_s(htmlfile, "html/index.html"); } else if (strcmp(head.path, "/") == 0) { strcpy_s(htmlfile, "html/index.html"); } else { strcpyn(htmlfile, head.path, 1, sizeof(head) - 1); } // 加载要显示的页面 struct fbuf *html = load_file(htmlfile); //printf("Loading file: %s\n", htmlfile); char *content; if (html == NULL) { content = (char *)calloc(BUF_SIZE, sizeof(char)); sprintf_s(content, BUF_SIZE, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s", 22, "<h1>404 NOT FOUND</h1>"); send(client, content, strlen(content), 0); } else { size_t total_size = html->buf_size + 67; content = (char *)calloc(total_size, sizeof(char)); sprintf_s(content, total_size, "HTTP/1.1 200 OK\r\nContent-Type: %s\r\nContent-Length: %d\r\n\r\n", html->mime, html->buf_size * sizeof(char)); // send head send(client, content, strlen(content), 0); // send body send(client, html->buf, html->buf_size, 0); } free(content); free(html); closesocket(client); } closesocket(server_fd); }
int Http_handler::push(const char *data, int len){ const char *sub; int len_t; switch(state){ case request_head: printf("Http_handler state is request_head\n" ); request_header_buffer.append(data,len); request_header_parsed=parse_request_head(); if(request_header_parsed){ state=response_head; } break; case response_head: printf("Http_handler state is response_head\n" ); sub=strstr((const char*)data,"\r\n\r\n"); if(sub!=NULL){ sub+=4; len_t=sub-data; response_header_len+=len_t; // response_header_len 必需先初始化为0 // 现在已经没有用了 response_header_buffer.append(data,len_t); if((response_header_parsed=parse_response_head())==true){ // state=response_body_have_length; //head结束,应该来body了 //让 parse 去改变状态 data=sub; len-=len_t; if(len>0){ push(data,len); } } }else{ //sub==NULL //两种情况,一是请求格式不标准,是以\n\n结尾;二是头部太长,分开几部分传输 response_header_buffer.append(data,response_header_len); //只考虑第二种情况 return 0; } if (len==0){ return 0; } break; case response_body_have_length: printf("Http_handler state is response_body\n" ); if(body_parsed){ printf("[!]error state!"); clear(); push(data,len); } if(len>0 && !chunked){ //chunked 在parse_response_head()中分析 printf("not chunked,data length is %d\n",len); body_buffer.append(data, len); if(body_buffer.length()==body_len){ //body_len 在parse_response_head()中分析 decoded_body_buffer=dezip(); dump_file(decoded_body_buffer,file_extention); //todo remove decoded_body_buffer=decode(); body_parsed=true; } } break; case response_body_chuncked_header: printf("Http_handler state is response_body_chuncked_header\n" ); if(len==0){ printf("data length is 0, end\n"); //两难抉择,浏览器会先加载一部分内容,等之后的数据包到达 //可是我们的分析程序会面临重复分析,状态不确定的问题 //dump_file(decoded_body_buffer,file_extention); // // decoded_body_buffer=decode(); // body_parsed=true; //为真,会调用clear return 0; //chunk end } sub=strstr(data,"\r\n"); if(sub==NULL){ printf("[!] can not file \\r\\n in chunk body. this is not chunked?\n"); clear(); return -1; } if(1==sscanf(data,"%x",&len_t)){ printf("chunked data,data length is %d\n",len_t); if(len_t==0){ printf("this chunk length is 0, end\n"); dump_file(decoded_body_buffer, file_extention); if(html_type){ decoded_body_buffer=decode(); body_parsed=true; }else{ state=request_head; // } return 0; //chunk end } else{ sub+=2; len-=(sub-data); body_len=len_t; state=response_body_chuncked_body; return push(sub,len); } } else{ printf("[!]chunk parse error!"); clear(); return -1; } // sscanf if end break; case response_body_chuncked_body: printf("Http_handler state is response_body_chuncked_body, chunk length is %d, data length is %d, buffer already have %d\n", body_len,len,body_buffer.length() ); if(len+body_buffer.length()<=body_len){ //这个body_len在上面分析 body_buffer.append(data,len); return 0; } else{ printf("[*]this chunk full!\n"); len_t=body_len-body_buffer.length(); body_buffer.append(data, len_t); decoded_body_buffer+=dezip(); // dump_file(decoded_body_buffer,file_extention); //todo remove // decoded_body_buffer=decode(); // body_parsed=true; len_t+=2; data+=len_t; len-=len_t; state=response_body_chuncked_header; push(data,len); } break; case unusable: printf("Http_handler state is unusable\n" ); break; } //switch end return 0; }