static int set_ready_fd(int fd, ofp_fd_set *fd_set, int(*is_ready)(int fd)) { if (OFP_FD_ISSET(fd, fd_set) && is_ready(fd)) return 1; OFP_FD_CLR(fd, fd_set); return 0; }
static void *webserver(void *arg) { int serv_fd, tmp_fd, nfds; unsigned int alen; struct ofp_sockaddr_in my_addr, caller; ofp_fd_set read_fd; (void)arg; OFP_INFO("HTTP thread started"); if (ofp_init_local()) { OFP_ERR("Error: OFP local init failed.\n"); return NULL; } sleep(1); myaddr = ofp_port_get_ipv4_addr(0, 0, OFP_PORTCONF_IP_TYPE_IP_ADDR); if ((serv_fd = ofp_socket(OFP_AF_INET, OFP_SOCK_STREAM, OFP_IPPROTO_TCP)) < 0) { OFP_ERR("ofp_socket failed"); perror("serv socket"); return NULL; } memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = OFP_AF_INET; my_addr.sin_port = odp_cpu_to_be_16(2048); my_addr.sin_addr.s_addr = myaddr; my_addr.sin_len = sizeof(my_addr); if (ofp_bind(serv_fd, (struct ofp_sockaddr *)&my_addr, sizeof(struct ofp_sockaddr)) < 0) { OFP_ERR("Cannot bind http socket (%s)!", ofp_strerror(ofp_errno)); return 0; } ofp_listen(serv_fd, 10); OFP_FD_ZERO(&read_fd); nfds = serv_fd; for ( ; ; ) { int r, i; static char buf[1024]; struct ofp_timeval timeout; timeout.tv_sec = 0; timeout.tv_usec = 200000; OFP_FD_SET(serv_fd, &read_fd); monitor_connections(&read_fd); r = ofp_select(nfds + 1, &read_fd, NULL, NULL, &timeout); if (r <= 0) continue; if (OFP_FD_ISSET(serv_fd, &read_fd)) { alen = sizeof(caller); if ((tmp_fd = ofp_accept(serv_fd, (struct ofp_sockaddr *)&caller, &alen)) > 0) { OFP_INFO("accept fd=%d", tmp_fd); for (i = 0; i < NUM_CONNECTIONS; i++) if (connections[i].fd == 0) break; if (i >= NUM_CONNECTIONS) { OFP_ERR("Node cannot accept new connections!"); ofp_close(tmp_fd); continue; } #if 0 struct ofp_linger so_linger; so_linger.l_onoff = 1; so_linger.l_linger = 0; int r1 = ofp_setsockopt(tmp_fd, OFP_SOL_SOCKET, OFP_SO_LINGER, &so_linger, sizeof so_linger); if (r1) OFP_ERR("SO_LINGER failed!"); #endif struct ofp_timeval tv; tv.tv_sec = 3; tv.tv_usec = 0; int r2 = ofp_setsockopt(tmp_fd, OFP_SOL_SOCKET, OFP_SO_SNDTIMEO, &tv, sizeof tv); if (r2) OFP_ERR("SO_SNDTIMEO failed!"); connections[i].fd = tmp_fd; connections[i].addr = caller.sin_addr.s_addr; connections[i].closed = FALSE; if (tmp_fd > nfds) nfds = tmp_fd; } } for (i = 0; i < NUM_CONNECTIONS; i++) { if (connections[i].fd == 0) continue; if (!(OFP_FD_ISSET(connections[i].fd, &read_fd))) continue; r = ofp_recv(connections[i].fd, buf, sizeof(buf)-1, 0); if (r > 0) { buf[r] = 0; OFP_INFO("recv data: %s", buf); if (!strncmp(buf, "GET", 3)) analyze_http(buf, connections[i].fd); else OFP_INFO("Not a HTTP GET request"); OFP_INFO("closing %d\n", connections[i].fd); OFP_FD_CLR(connections[i].fd, &read_fd); while (ofp_close(connections[i].fd) < 0) { OFP_ERR("ofp_close failed, fd=%d err='%s'", connections[i].fd, ofp_strerror(ofp_errno)); sleep(1); } OFP_INFO("closed fd=%d", connections[i].fd); connections[i].fd = 0; } else if (r == 0) { if (connections[i].post) { OFP_INFO("File download finished"); fclose(connections[i].post); connections[i].post = NULL; } ofp_close(connections[i].fd); OFP_FD_CLR(connections[i].fd, &read_fd); connections[i].fd = 0; } } } OFP_INFO("httpd exiting"); return NULL; }