/* * Create non-blocking socket and bind to the given port. */ int create_and_bind(unsigned short port) { int sd = -1; /* Listen socket. */ struct sockaddr_in sa; /* Address of RTSP listen socket. */ int reuse = 1; memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(port); sd = socket(AF_INET, SOCK_STREAM, 0); if (sd < 0) { printd(EMERG "Create rtsp server listening socket error"); return -1; } /* Set socket in nonblock mode. */ if (set_block_mode(sd, 0) < 0) { goto err; } if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { printd(ERR "Set listening socket option[SO_REUSEADDR] error"); goto err; } if (bind(sd, (struct sockaddr *)&sa, sizeof(sa)) < 0) { printd(EMERG "Bind listening sockaddr to local port[%hd] error: %s\n", port, strerror(errno)); goto err; } return sd; err: close(sd); return -1; }
/* Like read(2), but if read fails due to non-blocking flag, resets flag * and restarts read. */ int blocking_read(int fd, char *buf, int nbytes) { int ret; int tried_reset = 0; while ((ret = (int)read(fd, buf, nbytes)) < 0) { if (!tried_reset && (errno == EAGAIN #ifdef EWOULDBLOCK || errno == EWOULDBLOCK #endif /* EWOULDBLOCK */ )) { int oerrno = errno; if (set_block_mode(fd, 1) > 0) { tried_reset = 1; continue; } errno = oerrno; } break; } return ret; }
int tcpclient_open(urg_tcpclient_t* cli, const char* ip_str, int port_num) { enum { Connect_timeout_second = 2 }; fd_set rmask, wmask; struct timeval tv = { Connect_timeout_second, 0 }; #if defined(URG_WINDOWS_OS) u_long flag; #else int flag; int sock_optval = -1; int sock_optval_size = sizeof(sock_optval); #endif int ret; cli->sock_desc = Invalid_desc; cli->pushed_back = -1; // no pushed back char. #if defined(URG_WINDOWS_OS) { static int is_initialized = 0; WORD wVersionRequested = 0x0202; WSADATA WSAData; int err; if (!is_initialized) { err = WSAStartup(wVersionRequested, &WSAData); if (err != 0) { return -1; } is_initialized = 1; } } #endif tcpclient_buffer_init(cli); cli->sock_addr_size = sizeof (struct sockaddr_in); if ((cli->sock_desc = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) { return -1; } memset((char*)&(cli->server_addr), 0, sizeof(cli->sock_addr_size)); cli->server_addr.sin_family = AF_INET; cli->server_addr.sin_port = htons(port_num); if (!strcmp(ip_str, "localhost")) { ip_str = "127.0.0.1"; } /* bind is not required, and port number is dynamic */ if ((cli->server_addr.sin_addr.s_addr = inet_addr(ip_str)) == INADDR_NONE) { return -1; } #if defined(URG_WINDOWS_OS) // Configures non-blocking mode flag = 1; ioctlsocket(cli->sock_desc, FIONBIO, &flag); if (connect(cli->sock_desc, (const struct sockaddr *)&(cli->server_addr), cli->sock_addr_size) == SOCKET_ERROR) { int error_number = WSAGetLastError(); if (error_number != WSAEWOULDBLOCK) { tcpclient_close(cli); return -1; } FD_ZERO(&rmask); FD_SET((SOCKET)cli->sock_desc, &rmask); wmask = rmask; ret = select((int)cli->sock_desc + 1, &rmask, &wmask, NULL, &tv); if (ret == 0) { // Operation timed out tcpclient_close(cli); return -2; } } // Returns to blocking mode set_block_mode(cli); #else // Configures non-blocking mode flag = fcntl(cli->sock_desc, F_GETFL, 0); fcntl(cli->sock_desc, F_SETFL, flag | O_NONBLOCK); if (connect(cli->sock_desc, (const struct sockaddr *)&(cli->server_addr), cli->sock_addr_size) < 0) { if (errno != EINPROGRESS) { tcpclient_close(cli); return -1; } // EINPROGRESS: a connection request was already received and not completed yet FD_ZERO(&rmask); FD_SET(cli->sock_desc, &rmask); wmask = rmask; ret = select(cli->sock_desc + 1, &rmask, &wmask, NULL, &tv); if (ret <= 0) { // Operation timed out tcpclient_close(cli); return -2; } if (getsockopt(cli->sock_desc, SOL_SOCKET, SO_ERROR, (int*)&sock_optval, (socklen_t*)&sock_optval_size) != 0) { // Connection failed tcpclient_close(cli); return -3; } if (sock_optval != 0) { // Connection failed tcpclient_close(cli); return -4; } // Returns to blocking mode set_block_mode(cli); } #endif return 0; }
int tcpclient_open(tcpclient_t* cli, const char* ip_str, int port_num) { enum { Connect_timeout_second = 2 }; fd_set rmask, wmask; struct timeval tv = { Connect_timeout_second, 0 }; int flag; int sock_optval = -1; int sock_optval_size = sizeof(sock_optval); int ret; cli->sock_desc = Invalid_desc; cli->pushed_back = -1; // no pushed back char. tcpclient_buffer_init(cli); cli->sock_addr_size = sizeof (struct sockaddr_in); if ((cli->sock_desc = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) { return -1; } memset((char*)&(cli->server_addr), 0, sizeof(cli->sock_addr_size)); cli->server_addr.sin_family = AF_INET; cli->server_addr.sin_port = htons(port_num); if (!strcmp(ip_str, "localhost")) { ip_str = "127.0.0.1"; } /* bind is not required, and port number is dynamic */ if ((cli->server_addr.sin_addr.s_addr = inet_addr(ip_str)) == INADDR_NONE) { return -1; } flag = fcntl(cli->sock_desc, F_GETFL, 0); fcntl(cli->sock_desc, F_SETFL, flag | O_NONBLOCK); //printf("cli->sock_desc: %d\n",cli->sock_desc); if (connect(cli->sock_desc, (const struct sockaddr *)&(cli->server_addr), cli->sock_addr_size) < 0) { if (errno != EINPROGRESS) { tcpclient_close(cli); return -1; } // EINPROGRESS: FD_ZERO(&rmask); FD_SET(cli->sock_desc, &rmask); wmask = rmask; ret = select(cli->sock_desc + 1, &rmask, &wmask, NULL, &tv); if (ret <= 0) { tcpclient_close(cli); return -2; } if (getsockopt(cli->sock_desc, SOL_SOCKET, SO_ERROR, (int*)&sock_optval, (socklen_t*)&sock_optval_size) != 0) { tcpclient_close(cli); return -3; } if (sock_optval != 0) { tcpclient_close(cli); return -4; } set_block_mode(cli); } //printf("connection ok!\n"); return 0; }