int sock_connect (const char *url, GError **err) { struct sockaddr_storage sas; gsize sas_len = sizeof(sas); if (!grid_string_to_sockaddr (url, (struct sockaddr*) &sas, &sas_len)) { g_error_transmit(err, NEWERROR(EINVAL, "invalid URL")); return -1; } int fd = socket_nonblock(sas.ss_family, SOCK_STREAM, 0); if (0 > fd) { g_error_transmit(err, NEWERROR(EINVAL, "socket error: (%d) %s", errno, strerror(errno))); return -1; } sock_set_reuseaddr(fd, TRUE); if (0 != metautils_syscall_connect (fd, (struct sockaddr*)&sas, sas_len)) { if (errno != EINPROGRESS && errno != 0) { g_error_transmit(err, NEWERROR(EINVAL, "connect error: (%d) %s", errno, strerror(errno))); metautils_pclose (&fd); return -1; } } sock_set_linger_default(fd); sock_set_nodelay(fd, TRUE); sock_set_tcpquickack(fd, TRUE); *err = NULL; return fd; }
int socket_connect(int sfd, const char *ip, const char *port) { struct sockaddr_in server_addr; #ifdef WIN //初始化WinSock struct WSAData wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { //初始化WinSock失败 LOG_ERROR("wsastartup failed with error "); return -1; } #endif memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(ip); server_addr.sin_port = htons(atoi(port)); if(connect(sfd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) { LOG_ERROR("connect error"); return -2; } if (socket_nonblock (sfd) < 0) { LOG_ERROR("nonblock error !"); return -3; } LOG_INFO("connected to server(ip=%s, port=%s, fd=%d)",ip,port,sfd); return sfd; }
static int start_unix_server(GError **error) { struct sockaddr_un local; worker_data_t wdata; memset(&wdata, 0x00, sizeof(wdata)); memset(&local, 0x00, sizeof(local)); memset(&worker_unix, 0, sizeof(worker_t)); /* Create ressources to monitor */ sock_unix = socket_nonblock(PF_UNIX, SOCK_STREAM, 0); if (sock_unix < 0) { GSETERROR(error, "Failed to create socket : %s", strerror(errno)); return(0); } /* Bind to file */ local.sun_family = AF_UNIX; g_strlcpy(local.sun_path, unix_socket_path, sizeof(local.sun_path)-1); if (-1 == bind(sock_unix, (struct sockaddr *)&local, sizeof(local))) { GSETERROR(error, "Failed to bind socket %d to file %s : %s", sock_unix, unix_socket_path, strerror(errno)); metautils_pclose(&sock_unix); return(0); } /* Listen on that socket */ if (-1 == listen(sock_unix, unix_socket_backlog)) { GSETERROR(error, "Failed to listen on socket %d : %s", sock_unix, strerror(errno)); metautils_pclose(&sock_unix); return(0); } if (!set_unix_permissions(unix_socket_path, error)) { GSETERROR(error, "Failed to set proper permissions on socket %d", sock_unix); metautils_pclose(&sock_unix); return(0); } /* Create worker */ wdata.fd = sock_unix; wdata.sock_timeout = unix_socket_timeout; worker_unix.func = accept_worker; worker_unix.timeout.startup = 0; worker_unix.timeout.activity = 0; memcpy(&(worker_unix.data), &wdata, sizeof(worker_data_t)); /* Accept new connection */ if (!add_fd_to_io_scheduler(&worker_unix, EPOLLIN, error)) { GSETERROR(error,"Failed to add server sock to io_scheduler"); metautils_pclose(&sock_unix); return 0; } INFO("UNIX server started on socket %s", unix_socket_path); return(1); }
static int start_inet_server(GError **error) { struct sockaddr_in sin; worker_data_t wdata; DEBUG("Starting an INET server bond on 127.0.0.1:%d", inet_socket_port); memset(&wdata, 0x00, sizeof(wdata)); memset(&worker_inet, 0, sizeof(worker_t)); /* Create ressources to monitor */ sock_inet = socket_nonblock(PF_INET, SOCK_STREAM, 0); if (sock_inet < 0) { GSETERROR(error, "Failed to create socket : %s", strerror(errno)); return(0); } sock_set_reuseaddr(sock_inet, TRUE); /* Bind to file */ memset(&sin, 0x00, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(inet_socket_port); if (!inet_aton("127.0.0.1", &(sin.sin_addr))) { GSETERROR(error,"Invalid address : 127.0.0.1 !!!"); return 0; } if (-1 == bind(sock_inet, (struct sockaddr *)&sin, sizeof(sin))) { GSETERROR(error, "Failed to bind socket [%d] to address 127.0.0.1 : %s", sock_inet, strerror(errno)); return(0); } /* Listen on that socket */ if (-1 == listen(sock_inet, inet_socket_backlog)) { GSETERROR(error, "Failed to listen on socket [%d] : %s", sock_inet, strerror(errno)); return(0); } /* Create worker */ wdata.fd = sock_inet; wdata.sock_timeout = inet_socket_timeout; worker_inet.func = accept_worker; worker_inet.timeout.startup = 0; worker_inet.timeout.activity = 0; memcpy(&(worker_inet.data), &wdata, sizeof(worker_data_t)); /* Accept new connection */ if (!add_fd_to_io_scheduler(&worker_inet, EPOLLIN, error)) { GSETERROR(error,"Failed to add server sock to io_scheduler"); return 0; } INFO("INET server started on socket fd=%d 127.0.0.1:%d", sock_inet, inet_socket_port); return(1); }
int socket_accept(int socket_id) { int result = accept(socket_id, NULL, NULL); if ( result < 0 && SOCKET_ERROR_FUNCTION() != SOCKET_AGAIN ) { return -1; } else if ( result < 0 ) { return 0; } socket_nonblock(result); return result; }
static bool cmd_init_stdin(rarch_cmd_t *handle) { #ifndef _WIN32 if (!socket_nonblock(STDIN_FILENO)) return false; #endif handle->stdin_enable = true; return true; }
int socket_bind(const char * ip, int port, int protocol) { int s; #ifdef __WIN32 SOCKADDR_IN sa; #else struct sockaddr_in sa; #endif if ((s = socket(AF_INET, protocol, 0)) < 0) { sys_err("socket: %s", strerror(errno)); return -1; } socket_reuse(s); #ifndef __WIN32__ socket_lingeroff(s); #else // Winsock2: SO_DONTLINGER, SO_KEEPALIVE, SO_LINGER, and SO_OOBINLINE are // not supported on sockets of type SOCK_DGRAM if (protocol == SOCK_STREAM) { socket_lingeroff(s); } #endif memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; //윈도우 서버는 개발용으로만 쓰기 때문에 BIND ip를 INADDR_ANY로 고정 //(테스트의 편의성을 위해) #ifndef __WIN32__ sa.sin_addr.s_addr = inet_addr(ip); #else sa.sin_addr.s_addr = INADDR_ANY; #endif sa.sin_port = htons((unsigned short) port); if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) { sys_err("bind: %s", strerror(errno)); return -1; } socket_nonblock(s); if (protocol == SOCK_STREAM) { sys_log(0, "SYSTEM: BINDING TCP PORT ON [%d] (fd %d)", port, s); listen(s, SOMAXCONN); } else sys_log(0, "SYSTEM: BINDING UDP PORT ON [%d] (fd %d)", port, s); return s; }
int socket_connect(int socket_id, char *ip, int port) { struct sockaddr_in address; memset(&address, 0, sizeof(struct sockaddr_in)); address.sin_family = AF_INET; address.sin_addr.s_addr = inet_addr(ip); address.sin_port = htons(port); if ( connect(socket_id, (const struct sockaddr *)&address, sizeof(address)) < 0 ) { return -1; } socket_nonblock(socket_id); return 0; }
static int net_http_new_socket(const char *domain, int port) { int fd; #ifndef _WIN32 #ifndef VITA struct timeval timeout; #endif #endif struct addrinfo hints, *addr = NULL; char portstr[16] = {0}; /* Initialize the network. */ if (!network_init()) return -1; snprintf(portstr, sizeof(portstr), "%i", port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = 0; if (getaddrinfo_retro(domain, portstr, &hints, &addr) < 0) return -1; if (!addr) return -1; fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); #ifndef _WIN32 #ifndef VITA timeout.tv_sec=4; timeout.tv_usec=0; setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout); #endif #endif if (connect(fd, addr->ai_addr, addr->ai_addrlen) != 0) { freeaddrinfo_retro(addr); socket_close(fd); return -1; } freeaddrinfo_retro(addr); if (!socket_nonblock(fd)) { socket_close(fd); return -1; } return fd; }
static bool remote_init_network(rarch_remote_t *handle, uint16_t port, unsigned user) { struct addrinfo hints = {0}; char port_buf[16] = {0}; struct addrinfo *res = NULL; int yes = 1; port = port + user; if (!network_init()) return false; RARCH_LOG("Bringing up remote interface on port %hu.\n", (unsigned short)port); #if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY) hints.ai_family = AF_INET; #else hints.ai_family = AF_UNSPEC; #endif hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; snprintf(port_buf, sizeof(port_buf), "%hu", (unsigned short)port); if (getaddrinfo_retro(NULL, port_buf, &hints, &res) < 0) goto error; handle->net_fd[user] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (handle->net_fd[user] < 0) goto error; if (!socket_nonblock(handle->net_fd[user])) goto error; setsockopt(handle->net_fd[user], SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(int)); if (bind(handle->net_fd[user], res->ai_addr, res->ai_addrlen) < 0) { RARCH_ERR("Failed to bind socket.\n"); goto error; } freeaddrinfo_retro(res); return true; error: if (res) freeaddrinfo_retro(res); return false; }
int socket_create_bind_connect(const char *ip, const char *port, const char *bport) { int sfd; struct sockaddr_in server_addr; #ifdef WIN //初始化WinSock struct WSAData wsaData; if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { //初始化WinSock失败 LOG_ERROR("wsastartup failed with error "); return -1; } #endif memset(&server_addr,0,sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(ip); server_addr.sin_port = htons(atoi(port)); sfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(sfd == INVALID_SOCKET) { LOG_ERROR("invalid socket !"); return sfd; } //绑定端口 sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); serverAddr.sin_port = htons(atoi(bport)); //绑定 int iErrorMsg = bind(sfd,(sockaddr*)&serverAddr,sizeof(serverAddr)); if (iErrorMsg < 0) { //绑定失败 LOG_ERROR("bind failed with error : %d",iErrorMsg); return -3; } if(connect(sfd,(struct sockaddr *)&server_addr,sizeof(server_addr)) < 0) { LOG_ERROR("connect error"); return -2; } if (socket_nonblock (sfd) < 0) { LOG_ERROR("nonblock error !"); return -3; } LOG_INFO("connected to server: ip[%s], port[%s], local fd[%d]",ip,port,sfd); return sfd; }
static bool cmd_init_network(rarch_cmd_t *handle, uint16_t port) { char port_buf[16]; struct addrinfo hints, *res = NULL; int yes = 1; if (!netplay_init_network()) return false; RARCH_LOG("Bringing up command interface on port %hu.\n", (unsigned short)port); memset(&hints, 0, sizeof(hints)); #if defined(_WIN32) || defined(HAVE_SOCKET_LEGACY) hints.ai_family = AF_INET; #else hints.ai_family = AF_UNSPEC; #endif hints.ai_socktype = SOCK_DGRAM; hints.ai_flags = AI_PASSIVE; snprintf(port_buf, sizeof(port_buf), "%hu", (unsigned short)port); if (getaddrinfo(NULL, port_buf, &hints, &res) < 0) goto error; handle->net_fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (handle->net_fd < 0) goto error; if (!socket_nonblock(handle->net_fd)) goto error; setsockopt(handle->net_fd, SOL_SOCKET, SO_REUSEADDR, CONST_CAST &yes, sizeof(int)); if (bind(handle->net_fd, res->ai_addr, res->ai_addrlen) < 0) { RARCH_ERR("Failed to bind socket.\n"); goto error; } freeaddrinfo(res); return true; error: if (res) freeaddrinfo(res); return false; }
static int net_http_new_socket(struct http_connection_t *conn) { int ret; struct addrinfo *addr = NULL, *next_addr = NULL; int fd = socket_init( (void**)&addr, conn->port, conn->domain, SOCKET_TYPE_STREAM); #ifdef HAVE_SSL if (conn->sock_state.ssl) { if (!(conn->sock_state.ssl_ctx = ssl_socket_init(fd, conn->domain))) return -1; } #endif next_addr = addr; while(fd >= 0) { #ifdef HAVE_SSL if (conn->sock_state.ssl) { ret = ssl_socket_connect(conn->sock_state.ssl_ctx, (void*)next_addr, true, true); if (ret >= 0) break; ssl_socket_close(conn->sock_state.ssl_ctx); } else #endif { ret = socket_connect(fd, (void*)next_addr, true); if (ret >= 0 && socket_nonblock(fd)) break; socket_close(fd); } fd = socket_next((void**)&next_addr); } if (addr) freeaddrinfo_retro(addr); conn->sock_state.fd = fd; return fd; }
int GB_CreateSocket(int type, int port) { int sockfd = -1; struct linger so_linger; int on; struct sockaddr_in seraddr; SN_MEMSET(&so_linger,0,sizeof(so_linger)); sockfd = socket(AF_INET, type, 0); if(sockfd < 0) { perror("GB_CreateSocket"); return -1; } socket_nonblock(sockfd, 1); so_linger.l_onoff = 1; so_linger.l_linger = 0; setsockopt(sockfd,SOL_SOCKET,SO_LINGER,&so_linger,sizeof(so_linger)); if(port > 0) { #if defined(SO_REUSEADDR) on = 1; if ((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) == -1) { perror("setsockopt SO_REUSEADDR error"); } #endif bzero(&seraddr,sizeof(seraddr)); seraddr.sin_family = AF_INET; seraddr.sin_addr.s_addr = htonl(INADDR_ANY); seraddr.sin_port= htons(port); if(bind(sockfd, (struct sockaddr*)&seraddr, sizeof(seraddr)) < 0) { perror("bind() error"); close(sockfd); return -1; } } return sockfd; }
int socket_listen(int socket_id, int port) { struct sockaddr_in address; memset(&address, 0, sizeof(struct sockaddr_in)); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(port); int yes = 1; if ( setsockopt(socket_id, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0 ) { return -1; } if ( bind(socket_id, (struct sockaddr *)&address, sizeof(address)) < 0 ) { return -1; } listen(socket_id, 5); socket_nonblock(socket_id); return 0; }
int socket_create_bind_listen(const char *ip, const char *port, bool isBlock/* = false*/) { int s, sfd; sfd = socket_create_bind(ip,port); if (isBlock == false) { s = socket_nonblock (sfd); if (s == -1) abort (); } s = listen (sfd, SOMAXCONN); if (s == -1) { perror ("listen"); abort (); } return sfd; }
static int _uconnect_path(const gchar *path, GError **err) { struct sockaddr_un local; memset(&local, 0x00, sizeof(local)); local.sun_family = AF_UNIX; g_strlcpy(local.sun_path, path, sizeof(local.sun_path)); int usock = socket_nonblock(PF_UNIX, SOCK_STREAM, 0); if (usock < 0) { GSETERROR(err, "socket(UNIX): (%d) %s", errno, strerror(errno)); return -1; } if (0 > connect(usock, (struct sockaddr *) &local, sizeof(local))) { GSETERROR(err, "connect(%s): (%d) %s", path, errno, strerror(errno)); metautils_pclose(&usock); return -1; } return usock; }
/* * Accept an incoming TCP connection on the given endpoint * Return values: * -1 [accept error] * -2 [getpeername error] */ int welcome (int fd, char ** remote, int * rport) { /* Local variables */ int fdnew; int retry = 10; struct sockaddr_in peeraddr; socklen_t peerlen = sizeof (peeraddr); struct hostent * rhost = NULL; /* Try to accept the connection */ do { errno = 0; fdnew = accept (fd, (struct sockaddr *) & peeraddr, & peerlen); } while (fdnew == -1 && errno == EINTR && retry --); if (fdnew == -1) return -1; /* Get the IP address of the calling application and retrieve its name */ memset ((char *) & peeraddr, '\0', sizeof (peeraddr)); if (getpeername (fdnew, (struct sockaddr *) & peeraddr, & peerlen)) { close (fd); return -2; } /* Then lookup for a name. * I do not a forward lookup because I do not care of possible spoofing */ rhost = gethostbyaddr ((char *) & peeraddr . sin_addr, sizeof (peeraddr . sin_addr), AF_INET); * rport = ntohs (peeraddr . sin_port); * remote = rhost ? strdup (rhost -> h_name) : strdup (inet_ntoa (peeraddr . sin_addr)); setsockopt_aggressive (fdnew); socket_nonblock (fdnew); return fdnew; }
static bool input_remote_init_network(input_remote_t *handle, uint16_t port, unsigned user) { int fd; struct addrinfo *res = NULL; port = port + user; if (!network_init()) return false; RARCH_LOG("Bringing up remote interface on port %hu.\n", (unsigned short)port); fd = socket_init((void**)&res, port, NULL, SOCKET_TYPE_DATAGRAM); if (fd < 0) goto error; handle->net_fd[user] = fd; if (!socket_nonblock(handle->net_fd[user])) goto error; if (!socket_bind(handle->net_fd[user], res)) { RARCH_ERR("Failed to bind socket.\n"); goto error; } freeaddrinfo_retro(res); return true; error: if (res) freeaddrinfo_retro(res); return false; }
socket_t socket_accept(socket_t s, struct sockaddr_in *peer) { socket_t desc; socklen_t i; i = sizeof(*peer); if ((desc = accept(s, (struct sockaddr *) peer, &i)) == -1) { sys_err("accept: %s (fd %d)", strerror(errno), s); return -1; } if (desc >= 65500) { sys_err("SOCKET FD 65500 LIMIT! %d", desc); socket_close(s); return -1; } socket_nonblock(desc); socket_lingeroff(desc); return (desc); }
static int net_http_new_socket(const char *domain, int port) { int ret; struct addrinfo *addr = NULL; int fd = socket_init((void**)&addr, port, domain, SOCKET_TYPE_STREAM); if (fd < 0) return -1; ret = socket_connect(fd, (void*)addr, true); freeaddrinfo_retro(addr); if (ret < 0) goto error; if (!socket_nonblock(fd)) goto error; return fd; error: socket_close(fd); return -1; }
static int muse_connect( const char* host, int port ) { int rsrv = INVALID_SOCKET; struct sockaddr_in rsrvINETAddress; struct sockaddr *rsrvSockAddrPtr = NULL; int selret, conret; struct timeval tval = {5, 0}; fd_set rset, wset; rsrvSockAddrPtr = (struct sockaddr*)&rsrvINETAddress; memset( (char*)&rsrvINETAddress, 0, sizeof(rsrvINETAddress) ); rsrvINETAddress.sin_family = AF_INET; rsrvINETAddress.sin_addr.s_addr = host_to_ip( host ); rsrvINETAddress.sin_port = htons( port ); rsrv = socket( AF_INET, SOCK_STREAM, 0 ); if ( !socket_nonblock(rsrv) ) { close( rsrv ); return INVALID_SOCKET; } conret = rconnect( rsrv, (struct sockaddr*)rsrvSockAddrPtr, sizeof(rsrvINETAddress) ); if ( conret == 0 ) goto ok; if ( conret < 0 && errno != EINPROGRESS ) { close( rsrv ); return INVALID_SOCKET; } errno = 0; /* * Else wait for connection. Cannot use cfgst_microsleep */ FD_ZERO( &rset ); FD_SET( rsrv, &rset ); wset = rset; selret = rselect( rsrv+1, &rset, &wset, NULL, &tval ); if ( selret == 0 ) { close( rsrv ); /* timeout */ errno = ETIMEDOUT; return INVALID_SOCKET; } if ( FD_ISSET(rsrv, &rset) || FD_ISSET(rsrv, &wset) ) { int error=0, optret, len=sizeof(error); optret = getsockopt( rsrv, SOL_SOCKET, SO_ERROR, &error, (socklen_t*)&len ); if ( optret < 0 || error != 0 ) { /* Solaris pending error */ errno = error; warning(" SOL_SOCKET SO_ERROR=%d", error); /*perror( "cfgst_connect" );*/ close( rsrv ); return INVALID_SOCKET; } } else { warning(" select error: sockfd not set"); close( rsrv ); return INVALID_SOCKET; } if ( !socket_block(rsrv) ) { close( rsrv ); return INVALID_SOCKET; } ok: notice("Connected to %s:%d", host, port); return rsrv; }
int main(int argc, char *argv[]) { struct sockaddr_in sa; char *msg; int sleep_val, i, msg_size; if (argc != 6) { printf("Usage: %s <ip> <port> <msg size> <sleep_val> <conns>\n", argv[0]); return -1; } sleep_val = atoi(argv[4]); sleep_val = sleep_val == 0 ? 1 : sleep_val; msg_size = atoi(argv[3]); msg_size = msg_size < (sizeof(unsigned long long)*2) ? (sizeof(unsigned long long)*2) : msg_size; msg = malloc(msg_size); rcv_msg = malloc(msg_size); conns = atoi(argv[5]); conn_fds = malloc(conns * sizeof(int)); if (!conn_fds || !msg || !rcv_msg) return -1; sa.sin_family = AF_INET; sa.sin_port = htons(atoi(argv[2])); sa.sin_addr.s_addr = inet_addr(argv[1]); for (i = 0 ; i < conns ; i++) { if ((conn_fds[i] = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("Establishing socket"); fflush(stdout); return -1; } if (socket_nonblock(conn_fds[i])) return -1; if (connect(conn_fds[i], (struct sockaddr*)&sa, sizeof(sa)) && errno != EINPROGRESS) { perror("connecting"); return -1; } } printf("Start communication\n"); fflush(stdout); start_timers(); while (1) { int i, j; construct_header(msg); for (i = 0 ; i < conns ; i++) { if (write(conn_fds[i], msg, msg_size) < 0 && errno != EINTR && errno != EAGAIN) { perror("sendto"); fflush(stdout); return -1; } if (errno != EINTR || errno != EAGAIN) { msg_sent++; } for (j = 0 ; j < sleep_val ; j++) { do_recv_proc(conn_fds[i], msg_size); } } //nanosleep(&ts, NULL); } return 0; }
/** * netplay_sync_pre_frame * @netplay : pointer to netplay object * * Pre-frame for Netplay synchronization. */ bool netplay_sync_pre_frame(netplay_t *netplay) { retro_ctx_serialize_info_t serial_info; if (netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->run_ptr], netplay->run_frame_count)) { serial_info.data_const = NULL; serial_info.data = netplay->buffer[netplay->run_ptr].state; serial_info.size = netplay->state_size; memset(serial_info.data, 0, serial_info.size); if ((netplay->quirks & NETPLAY_QUIRK_INITIALIZATION) || netplay->run_frame_count == 0) { /* Don't serialize until it's safe */ } else if (!(netplay->quirks & NETPLAY_QUIRK_NO_SAVESTATES) && core_serialize(&serial_info)) { if (netplay->force_send_savestate && !netplay->stall && !netplay->remote_paused) { /* Bring our running frame and input frames into parity so we don't * send old info */ if (netplay->run_ptr != netplay->self_ptr) { memcpy(netplay->buffer[netplay->self_ptr].state, netplay->buffer[netplay->run_ptr].state, netplay->state_size); netplay->run_ptr = netplay->self_ptr; netplay->run_frame_count = netplay->self_frame_count; } /* Send this along to the other side */ serial_info.data_const = netplay->buffer[netplay->run_ptr].state; netplay_load_savestate(netplay, &serial_info, false); netplay->force_send_savestate = false; } } else { /* If the core can't serialize properly, we must stall for the * remote input on EVERY frame, because we can't recover */ netplay->quirks |= NETPLAY_QUIRK_NO_SAVESTATES; netplay->stateless_mode = true; } /* If we can't transmit savestates, we must stall until the client is ready */ if (netplay->run_frame_count > 0 && (netplay->quirks & (NETPLAY_QUIRK_NO_SAVESTATES|NETPLAY_QUIRK_NO_TRANSMISSION)) && (netplay->connections_size == 0 || !netplay->connections[0].active || netplay->connections[0].mode < NETPLAY_CONNECTION_CONNECTED)) netplay->stall = NETPLAY_STALL_NO_CONNECTION; } if (netplay->is_server) { fd_set fds; struct timeval tmp_tv = {0}; int new_fd; struct sockaddr_storage their_addr; socklen_t addr_size; struct netplay_connection *connection; size_t connection_num; /* Check for a connection */ FD_ZERO(&fds); FD_SET(netplay->listen_fd, &fds); if (socket_select(netplay->listen_fd + 1, &fds, NULL, NULL, &tmp_tv) > 0 && FD_ISSET(netplay->listen_fd, &fds)) { addr_size = sizeof(their_addr); new_fd = accept(netplay->listen_fd, (struct sockaddr*)&their_addr, &addr_size); if (new_fd < 0) { RARCH_ERR("%s\n", msg_hash_to_str(MSG_NETPLAY_FAILED)); goto process; } /* Set the socket nonblocking */ if (!socket_nonblock(new_fd)) { /* Catastrophe! */ socket_close(new_fd); goto process; } #if defined(IPPROTO_TCP) && defined(TCP_NODELAY) { int flag = 1; if (setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, #ifdef _WIN32 (const char*) #else (const void*) #endif &flag, sizeof(int)) < 0) RARCH_WARN("Could not set netplay TCP socket to nodelay. Expect jitter.\n"); } #endif #if defined(F_SETFD) && defined(FD_CLOEXEC) /* Don't let any inherited processes keep open our port */ if (fcntl(new_fd, F_SETFD, FD_CLOEXEC) < 0) RARCH_WARN("Cannot set Netplay port to close-on-exec. It may fail to reopen if the client disconnects.\n"); #endif /* Allocate a connection */ for (connection_num = 0; connection_num < netplay->connections_size; connection_num++) if (!netplay->connections[connection_num].active && netplay->connections[connection_num].mode != NETPLAY_CONNECTION_DELAYED_DISCONNECT) break; if (connection_num == netplay->connections_size) { if (connection_num == 0) { netplay->connections = (struct netplay_connection*)malloc(sizeof(struct netplay_connection)); if (netplay->connections == NULL) { socket_close(new_fd); goto process; } netplay->connections_size = 1; } else { size_t new_connections_size = netplay->connections_size * 2; struct netplay_connection *new_connections = (struct netplay_connection*) realloc(netplay->connections, new_connections_size*sizeof(struct netplay_connection)); if (new_connections == NULL) { socket_close(new_fd); goto process; } memset(new_connections + netplay->connections_size, 0, netplay->connections_size * sizeof(struct netplay_connection)); netplay->connections = new_connections; netplay->connections_size = new_connections_size; } } connection = &netplay->connections[connection_num]; /* Set it up */ memset(connection, 0, sizeof(*connection)); connection->active = true; connection->fd = new_fd; connection->mode = NETPLAY_CONNECTION_INIT; if (!netplay_init_socket_buffer(&connection->send_packet_buffer, netplay->packet_buffer_size) || !netplay_init_socket_buffer(&connection->recv_packet_buffer, netplay->packet_buffer_size)) { if (connection->send_packet_buffer.data) netplay_deinit_socket_buffer(&connection->send_packet_buffer); connection->active = false; socket_close(new_fd); goto process; } netplay_handshake_init_send(netplay, connection); } } process: netplay->can_poll = true; input_poll_net(); return (netplay->stall != NETPLAY_STALL_NO_CONNECTION); }
/* FIX! make service return error instead of invoking exit() */ int add_service(char *name, const char *port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t input_handler, connection_closed_handler_t connection_closed_handler, void *priv) { struct service *c, **p; int so_reuseaddr_option = 1; c = malloc(sizeof(struct service)); c->name = strdup(name); c->port = strdup(port); c->max_connections = 1; /* Only TCP/IP ports can support more than one connection */ c->fd = -1; c->connections = NULL; c->new_connection = new_connection_handler; c->input = input_handler; c->connection_closed = connection_closed_handler; c->priv = priv; c->next = NULL; long portnumber; if (strcmp(c->port, "pipe") == 0) c->type = CONNECTION_STDINOUT; else { char *end; portnumber = strtol(c->port, &end, 0); if (!*end && (parse_long(c->port, &portnumber) == ERROR_OK)) { c->portnumber = portnumber; c->type = CONNECTION_TCP; } else c->type = CONNECTION_PIPE; } if (c->type == CONNECTION_TCP) { c->max_connections = max_connections; c->fd = socket(AF_INET, SOCK_STREAM, 0); if (c->fd == -1) { LOG_ERROR("error creating socket: %s", strerror(errno)); exit(-1); } setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, (void *)&so_reuseaddr_option, sizeof(int)); socket_nonblock(c->fd); memset(&c->sin, 0, sizeof(c->sin)); c->sin.sin_family = AF_INET; c->sin.sin_addr.s_addr = INADDR_ANY; c->sin.sin_port = htons(c->portnumber); if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { LOG_ERROR("couldn't bind to socket: %s", strerror(errno)); exit(-1); } #ifndef _WIN32 int segsize = 65536; setsockopt(c->fd, IPPROTO_TCP, TCP_MAXSEG, &segsize, sizeof(int)); #endif int window_size = 128 * 1024; /* These setsockopt()s must happen before the listen() */ setsockopt(c->fd, SOL_SOCKET, SO_SNDBUF, (char *)&window_size, sizeof(window_size)); setsockopt(c->fd, SOL_SOCKET, SO_RCVBUF, (char *)&window_size, sizeof(window_size)); if (listen(c->fd, 1) == -1) { LOG_ERROR("couldn't listen on socket: %s", strerror(errno)); exit(-1); } } else if (c->type == CONNECTION_STDINOUT) { c->fd = fileno(stdin); #ifdef _WIN32 /* for win32 set stdin/stdout to binary mode */ if (_setmode(_fileno(stdout), _O_BINARY) < 0) LOG_WARNING("cannot change stdout mode to binary"); if (_setmode(_fileno(stdin), _O_BINARY) < 0) LOG_WARNING("cannot change stdin mode to binary"); if (_setmode(_fileno(stderr), _O_BINARY) < 0) LOG_WARNING("cannot change stderr mode to binary"); #else socket_nonblock(c->fd); #endif } else if (c->type == CONNECTION_PIPE) { #ifdef _WIN32 /* we currenty do not support named pipes under win32 * so exit openocd for now */ LOG_ERROR("Named pipes currently not supported under this os"); exit(1); #else /* Pipe we're reading from */ c->fd = open(c->port, O_RDONLY | O_NONBLOCK); if (c->fd == -1) { LOG_ERROR("could not open %s", c->port); exit(1); } #endif } /* add to the end of linked list */ for (p = &services; *p; p = &(*p)->next) ; *p = c; return ERROR_OK; }
/** * netplay_new: * @direct_host : Netplay host discovered from scanning. * @server : IP address of server. * @port : Port of server. * @stateless_mode : Shall we use stateless mode? * @check_frames : Frequency with which to check CRCs. * @cb : Libretro callbacks. * @nat_traversal : If true, attempt NAT traversal. * @nick : Nickname of user. * @quirks : Netplay quirks required for this session. * * Creates a new netplay handle. A NULL server means we're * hosting. * * Returns: new netplay data. */ netplay_t *netplay_new(void *direct_host, const char *server, uint16_t port, bool stateless_mode, int check_frames, const struct retro_callbacks *cb, bool nat_traversal, const char *nick, uint64_t quirks) { netplay_t *netplay = (netplay_t*)calloc(1, sizeof(*netplay)); if (!netplay) return NULL; netplay->listen_fd = -1; netplay->tcp_port = port; netplay->cbs = *cb; netplay->connected_players = 0; netplay->player_max = 1; netplay->is_server = (direct_host == NULL && server == NULL); netplay->nat_traversal = netplay->is_server ? nat_traversal : false; netplay->stateless_mode = stateless_mode; netplay->check_frames = check_frames; netplay->crc_validity_checked = false; netplay->crcs_valid = true; netplay->quirks = quirks; netplay->self_mode = netplay->is_server ? NETPLAY_CONNECTION_PLAYING : NETPLAY_CONNECTION_NONE; if (netplay->is_server) { netplay->connections = NULL; netplay->connections_size = 0; } else { netplay->connections = &netplay->one_connection; netplay->connections_size = 1; netplay->connections[0].fd = -1; } strlcpy(netplay->nick, nick[0] ? nick : RARCH_DEFAULT_NICK, sizeof(netplay->nick)); if (!init_socket(netplay, direct_host, server, port)) { free(netplay); return NULL; } if (!netplay_init_buffers(netplay)) { free(netplay); return NULL; } if (!netplay->is_server) { netplay_handshake_init_send(netplay, &netplay->connections[0]); netplay->connections[0].mode = netplay->self_mode = NETPLAY_CONNECTION_INIT; } /* FIXME: Not really the right place to do this, socket initialization needs * to be fixed in general */ if (netplay->is_server) { if (!socket_nonblock(netplay->listen_fd)) goto error; } else { if (!socket_nonblock(netplay->connections[0].fd)) goto error; } return netplay; error: if (netplay->listen_fd >= 0) socket_close(netplay->listen_fd); if (netplay->connections && netplay->connections[0].fd >= 0) socket_close(netplay->connections[0].fd); free(netplay); return NULL; }