Exemple #1
0
static void network_cmd_poll(rarch_cmd_t *handle)
{
   fd_set fds;
   struct timeval tmp_tv = {0};

   if (handle->net_fd < 0)
      return;

   FD_ZERO(&fds);
   FD_SET(handle->net_fd, &fds);

   if (socket_select(handle->net_fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0)
      return;

   if (!FD_ISSET(handle->net_fd, &fds))
      return;

   for (;;)
   {
      char buf[1024];
      ssize_t ret = recvfrom(handle->net_fd, buf,
            sizeof(buf) - 1, 0, NULL, NULL);

      if (ret <= 0)
         break;

      buf[ret] = '\0';
      parse_msg(handle, buf);
   }
}
Exemple #2
0
/*-------------------------------------------------------------------------*\
* Waits for a set of sockets until a condition is met or timeout.
\*-------------------------------------------------------------------------*/
static int global_select(lua_State *L) {
    int rtab, wtab, itab, ret, ndirty;
    t_socket max_fd;
    fd_set rset, wset;
    t_timeout tm;
    double t = luaL_optnumber(L, 3, -1);
    FD_ZERO(&rset); FD_ZERO(&wset);
    lua_settop(L, 3);
    lua_newtable(L); itab = lua_gettop(L);
    lua_newtable(L); rtab = lua_gettop(L);
    lua_newtable(L); wtab = lua_gettop(L);
    max_fd = collect_fd(L, 1, SOCKET_INVALID, itab, &rset);
    ndirty = check_dirty(L, 1, rtab, &rset);
    t = ndirty > 0? 0.0: t;
    timeout_init(&tm, t, -1);
    timeout_markstart(&tm);
    max_fd = collect_fd(L, 2, max_fd, itab, &wset);
    ret = socket_select(max_fd+1, &rset, &wset, NULL, &tm);
    if (ret > 0 || ndirty > 0) {
        return_fd(L, &rset, max_fd+1, itab, rtab, ndirty);
        return_fd(L, &wset, max_fd+1, itab, wtab, 0);
        make_assoc(L, rtab);
        make_assoc(L, wtab);
        return 2;
    } else if (ret == 0) {
        lua_pushstring(L, "timeout");
        return 3;
    } else {
        lua_pushstring(L, "error");
        return 3;
    }
}
Exemple #3
0
char *http_get_status_code( int socket, int timeout )
{
    char *result = NULL;

    if( socket_select( socket, timeout ) == 0 )
    {
    	return result;
    }

    int buffer_length = 24;
    char *buffer = ( char * )malloc( buffer_length );
    if( socket_receive( socket, buffer, buffer_length ) != buffer_length )
    {
    	free( buffer );
    	return result;
    }

	result = ( char * )malloc( 4 );
	memcpy( result, buffer + 9, 3 );
	*( result + 3 ) = '\0';

    while( socket_receive( socket, buffer, buffer_length ) == buffer_length );
    free( buffer );
   
    return result;
}
Exemple #4
0
void socket_buf_clear(UDM_CONN *connp){
	char buf[1024];
	int len;
	do {
    		if (socket_select(connp, 0, 'r')==-1)
			return;
		len = recv(connp->conn_fd, buf, 1024,0);
	}while(len > 0);
}
Exemple #5
0
static int poll_input(netplay_t *netplay, bool block)
{
   bool had_input    = false;
   int max_fd        = netplay->fd + 1;
   struct timeval tv = {0};
   tv.tv_sec         = 0;
   tv.tv_usec        = block ? (RETRY_MS * 1000) : 0;

   do
   { 
      fd_set fds;
      /* select() does not take pointer to const struct timeval.
       * Technically possible for select() to modify tmp_tv, so 
       * we go paranoia mode. */
      struct timeval tmp_tv = tv;
      had_input = false;

      netplay->timeout_cnt++;

      FD_ZERO(&fds);
      FD_SET(netplay->fd, &fds);

      if (socket_select(max_fd, &fds, NULL, NULL, &tmp_tv) < 0)
         return -1;

      if (FD_ISSET(netplay->fd, &fds))
      {
         /* If we're not ready for input, wait until we are. 
          * Could fill the TCP buffer, stalling the other side. */
         if (netplay_delta_frame_ready(netplay,
                  &netplay->buffer[netplay->read_ptr],
                  netplay->read_frame_count))
         {
            had_input = true;
            if (!netplay_get_cmd(netplay))
               return -1;
         }
      }

      /* If we were blocked for input, pass if we have this frame's input */
      if (block && netplay->read_frame_count > netplay->self_frame_count)
         break;

      /* If we had input, we might have more */
      if (had_input || !block)
         continue;

      RARCH_LOG("Network is stalling at frame %u, count %u of %d ...\n",
            netplay->self_frame_count, netplay->timeout_cnt, MAX_RETRIES);

      if (netplay->timeout_cnt >= MAX_RETRIES && !netplay->remote_paused)
         return -1;
   } while (had_input || block);

   return 0;
}
Exemple #6
0
int socket_write(DPS_CONN *connp, const char *buf){
	
	if (socket_select(connp, DPS_NET_READ_TIMEOUT, 'w') == -1)
		return -1;

	if (DpsSend(connp->conn_fd, buf, dps_strlen(buf), 0) == -1){
		connp->err = DPS_NET_ERROR;
		return -1;
	}
	return 0;
}
Exemple #7
0
int socket_write(UDM_CONN *connp, const char *buf){
	
	if (socket_select(connp, UDM_NET_READ_TIMEOUT, 'w') == -1)
		return -1;

	if (UdmSend(connp->conn_fd, buf, strlen(buf), 0) == -1){
		connp->err = UDM_NET_ERROR;
		return -1;
	}
	return 0;
}
Exemple #8
0
static int poll_input(netplay_t *netplay, bool block)
{
    int max_fd        = (netplay->fd > netplay->udp_fd ?
                         netplay->fd : netplay->udp_fd) + 1;
    struct timeval tv = {0};
    tv.tv_sec         = 0;
    tv.tv_usec        = block ? (RETRY_MS * 1000) : 0;

    do
    {
        fd_set fds;
        /* select() does not take pointer to const struct timeval.
         * Technically possible for select() to modify tmp_tv, so
         * we go paranoia mode. */
        struct timeval tmp_tv = tv;

        netplay->timeout_cnt++;

        FD_ZERO(&fds);
        FD_SET(netplay->udp_fd, &fds);
        FD_SET(netplay->fd, &fds);

        if (socket_select(max_fd, &fds, NULL, NULL, &tmp_tv) < 0)
            return -1;

        /* Somewhat hacky,
         * but we aren't using the TCP connection for anything useful atm. */
        if (FD_ISSET(netplay->fd, &fds) && !netplay_get_cmd(netplay))
            return -1;

        if (FD_ISSET(netplay->udp_fd, &fds))
            return 1;

        if (!block)
            continue;

        if (!send_chunk(netplay))
        {
            warn_hangup();
            netplay->has_connection = false;
            return -1;
        }

        RARCH_LOG("Network is stalling, resending packet... Count %u of %d ...\n",
                  netplay->timeout_cnt, MAX_RETRIES);
    } while ((netplay->timeout_cnt < MAX_RETRIES) && block);

    if (block)
        return -1;
    return 0;
}
Exemple #9
0
int socket_read( DPS_CONN *connp, size_t maxsize){
        int num_read;
	size_t num_read_total;
	time_t t;

	num_read_total = 0;

	if (connp->buf)
		DPS_FREE(connp->buf);

	connp->buf_len_total = 0;
	connp->buf_len = 0;
	connp->err = 0;
	
	t = time(NULL);
	do {
	  if (socket_select(connp, connp->timeout, 'r') == -1){
			return -1;
		}

		if (connp->buf_len_total <= num_read_total+DPS_NET_BUF_SIZE){
			connp->buf_len_total += DPS_NET_BUF_SIZE;
			connp->buf = DpsXrealloc(connp->buf, (size_t)(connp->buf_len_total+1));
			if (connp->buf == NULL) return -1;
		}
		
/*		num_read = recv(connp->conn_fd, connp->buf + num_read_total, 
				(DPS_NET_BUF_SIZE <= maxsize - num_read_total) ? DPS_NET_BUF_SIZE : (maxsize - num_read_total),
				0);*/
		num_read = read(connp->conn_fd, connp->buf + num_read_total, 
				(DPS_NET_BUF_SIZE <= maxsize - num_read_total) ? DPS_NET_BUF_SIZE : (maxsize - num_read_total)
				);

		num_read_total += num_read;		

		if (num_read < 0){
			connp->err = DPS_NET_ERROR;
			return -1;
		}else if (num_read == 0) {
		  if ((size_t)(time(NULL) - t) > connp->timeout) break;
		} else t = time(NULL);
		if (num_read_total >=maxsize ){
			connp->err = DPS_NET_FILE_TL;
			break;
		}
	}while (num_read!=0);
	connp->buf_len = num_read_total;
	return num_read_total;	
}
Exemple #10
0
static int global_select(lua_State *L, const sigset_t* mask, int sigreceived) {
    int rtab, wtab, etab, itab, ret, ndirty;
    t_socket max_fd;
    fd_set rset, wset, eset;
    t_timeout tm;
    double t = luaL_optnumber(L, 4, -1);
    FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
    lua_settop(L, 4);
    lua_newtable(L); itab = lua_gettop(L);
    lua_newtable(L); rtab = lua_gettop(L);
    lua_newtable(L); wtab = lua_gettop(L);
    lua_newtable(L); etab = lua_gettop(L);
    max_fd = collect_fd(L, 1, SOCKET_INVALID, itab, &rset);
    ndirty = check_dirty(L, 1, rtab, &rset);
    t = ndirty > 0? 0.0: t;
    timeout_init(&tm, t, -1);
    timeout_markstart(&tm);
    max_fd = collect_fd(L, 2, max_fd, itab, &wset);
    max_fd = collect_fd(L, 3, max_fd, itab, &eset);
    //printf("+enter select\n");
    if (sigreceived) {
        ret = -1;
    } else {
        ret = socket_select(max_fd+1, &rset, &wset, &eset, &tm, mask);
    }
    //printf("+exit select\n");
    if (ret > 0 || ndirty > 0) {
        return_fd(L, &rset, max_fd+1, itab, rtab, ndirty);
        return_fd(L, &wset, max_fd+1, itab, wtab, 0);
        return_fd(L, &eset, max_fd+1, itab, etab, 0);
        make_assoc(L, rtab);
        make_assoc(L, wtab);
        make_assoc(L, etab);
        return 3; //3 values pushed: 3 result tables
    } else if (ret == 0) {
        lua_pushstring(L, "timeout");
        return 4; //4 values pushed: 3 result tables + timeout msg
    } else {
        lua_pushstring(L, strerror(errno));
        return 4; //4 values pushed: 3 result tables + errno msg
    }
}
Exemple #11
0
int Dps_ftp_read_line(DPS_CONN *connp){

	if (socket_select(connp, DPS_NET_READ_TIMEOUT, 'r')){
#ifdef DEBUG_FTP
	  fprintf(stderr, "ftp://%s (ftp_read_line-timeout-err): ", connp->hostname);
		/*DpsLog(connp->indexer, DPS_LOG_DEBUG, "ftp://%s (ftp_read_line-timeout-err): ", connp->hostname);*/
#endif
		return -1;
	}
	
		
	do {
		if (socket_read_line(connp) < 0)
			return -1;
		if (((connp->buf[0] =='1')||(connp->buf[0] =='2')||
		    (connp->buf[0] =='3')||(connp->buf[0] =='4')||
		    (connp->buf[0] =='5')) && (connp->buf[3] == ' '))
			break;
	}while( 1 );
	return 0;
}
Exemple #12
0
int		main(int argc, char **argv)
{
	t_socket	*socket;

	if (argc < 3)
	{
		ft_printf("Usage: client <host> <port>");
		return (0);
	}
	socket_set_default_read(def_read);
	socket_set_default_receive(def_receive);
	socket_set_default_error(def_err);
	socket = socket_create();
	socket_connect(socket, argv[1], ft_atoi(argv[2]));
	while (1 != 2)
	{
		socket_select(socket);
	}
	close(socket->fd);
	return (0);
}
Exemple #13
0
int socket_accept(UDM_CONN *connp){
	struct sockaddr sa;
	int sfd;
	socklen_t len;
        if (socket_select(connp, UDM_NET_ACC_TIMEOUT, 'r') == -1)
		return -1;

	len = sizeof(struct sockaddr);
						
	sfd = accept(connp->conn_fd, &sa, &len);
	socket_close(connp);

	if (sfd == -1){
		connp->err = UDM_NET_ERROR;
		return -1;
	}
	connp->conn_fd = sfd;
	
	memcpy(&connp->sin, &sa, sizeof(connp->sin));
	return 0;
}
int socket_wait_writable(struct mySocket *sock, struct timeval *timeout) {
	return socket_select(sock, timeout, 0, 1);
}
Exemple #15
0
int server_loop(struct command_context *command_context)
{
	struct service *service;

	bool poll_ok = true;

	/* used in select() */
	fd_set read_fds;
	int fd_max;

	/* used in accept() */
	int retval;

#ifndef _WIN32
	if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
		LOG_ERROR("couldn't set SIGPIPE to SIG_IGN");
#endif

	while (!shutdown_openocd) {
		/* monitor sockets for activity */
		fd_max = 0;
		FD_ZERO(&read_fds);

		/* add service and connection fds to read_fds */
		for (service = services; service; service = service->next) {
			if (service->fd != -1) {
				/* listen for new connections */
				FD_SET(service->fd, &read_fds);

				if (service->fd > fd_max)
					fd_max = service->fd;
			}

			if (service->connections) {
				struct connection *c;

				for (c = service->connections; c; c = c->next) {
					/* check for activity on the connection */
					FD_SET(c->fd, &read_fds);
					if (c->fd > fd_max)
						fd_max = c->fd;
				}
			}
		}

		struct timeval tv;
		tv.tv_sec = 0;
		if (poll_ok) {
			/* we're just polling this iteration, this is faster on embedded
			 * hosts */
			tv.tv_usec = 0;
			retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
		} else {
			/* Every 100ms */
			tv.tv_usec = 100000;
			/* Only while we're sleeping we'll let others run */
			openocd_sleep_prelude();
			kept_alive();
			retval = socket_select(fd_max + 1, &read_fds, NULL, NULL, &tv);
			openocd_sleep_postlude();
		}

		if (retval == -1) {
#ifdef _WIN32

			errno = WSAGetLastError();

			if (errno == WSAEINTR)
				FD_ZERO(&read_fds);
			else {
				LOG_ERROR("error during select: %s", strerror(errno));
				exit(-1);
			}
#else

			if (errno == EINTR)
				FD_ZERO(&read_fds);
			else {
				LOG_ERROR("error during select: %s", strerror(errno));
				exit(-1);
			}
#endif
		}

		if (retval == 0) {
			/* We only execute these callbacks when there was nothing to do or we timed
			 *out */
			target_call_timer_callbacks();
			process_jim_events(command_context);

			FD_ZERO(&read_fds);	/* eCos leaves read_fds unchanged in this case!  */

			/* We timed out/there was nothing to do, timeout rather than poll next time
			 **/
			poll_ok = false;
		} else {
			/* There was something to do, next time we'll just poll */
			poll_ok = true;
		}

		/* This is a simple back-off algorithm where we immediately
		 * re-poll if we did something this time around.
		 *
		 * This greatly improves performance of DCC.
		 */
		poll_ok = poll_ok || target_got_message();

		for (service = services; service; service = service->next) {
			/* handle new connections on listeners */
			if ((service->fd != -1)
			    && (FD_ISSET(service->fd, &read_fds))) {
				if (service->max_connections > 0)
					add_connection(service, command_context);
				else {
					if (service->type == CONNECTION_TCP) {
						struct sockaddr_in sin;
						socklen_t address_size = sizeof(sin);
						int tmp_fd;
						tmp_fd = accept(service->fd,
								(struct sockaddr *)&service->sin,
								&address_size);
						close_socket(tmp_fd);
					}
					LOG_INFO(
						"rejected '%s' connection, no more connections allowed",
						service->name);
				}
			}

			/* handle activity on connections */
			if (service->connections) {
				struct connection *c;

				for (c = service->connections; c; ) {
					if ((FD_ISSET(c->fd, &read_fds)) || c->input_pending) {
						retval = service->input(c);
						if (retval != ERROR_OK) {
							struct connection *next = c->next;
							if (service->type == CONNECTION_PIPE) {
								/* if connection uses a pipe then
								 *shutdown openocd on error */
								shutdown_openocd = 1;
							}
							remove_connection(service, c);
							LOG_INFO("dropped '%s' connection",
								service->name);
							c = next;
							continue;
						}
					}
					c = c->next;
				}
			}
		}

#ifdef _WIN32
		MSG msg;
		while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
			if (msg.message == WM_QUIT)
				shutdown_openocd = 1;
		}
#endif
	}

	return ERROR_OK;
}
Exemple #16
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);
}
static bool netplay_lan_ad_client(void)
{
   fd_set fds;
   socklen_t addr_size;
   struct sockaddr their_addr;
   struct timeval tmp_tv = {0};

   if (lan_ad_client_fd < 0)
       return false;

   /* Check for any ad queries */
   while (1)
   {
      FD_ZERO(&fds);
      FD_SET(lan_ad_client_fd, &fds);
      if (socket_select(lan_ad_client_fd + 1,
               &fds, NULL, NULL, &tmp_tv) <= 0)
         break;

      if (!FD_ISSET(lan_ad_client_fd, &fds))
         break;

      /* Somebody queried, so check that it's valid */
      addr_size = sizeof(their_addr);

      if (recvfrom(lan_ad_client_fd, (char*)&ad_packet_buffer,
            sizeof(struct ad_packet), 0, &their_addr, &addr_size) >=
            (ssize_t) sizeof(struct ad_packet))
      {
         struct netplay_host *host = NULL;

         /* Make sure it's a valid response */
         if (memcmp((void *) &ad_packet_buffer, "RANS", 4))
            continue;

         /* For this version */
         if (ntohl(ad_packet_buffer.protocol_version) != NETPLAY_PROTOCOL_VERSION)
            continue;

         /* And that we know how to handle it */
         if (their_addr.sa_family == AF_INET)
         {
            struct sockaddr_in *sin = (struct sockaddr_in *) &their_addr;
            sin->sin_port = htons(ntohl(ad_packet_buffer.port));

         }
#ifdef HAVE_INET6
         else if (their_addr.sa_family == AF_INET6)
         {
            struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &their_addr;
            sin6->sin6_port = htons(ad_packet_buffer.port);

         }
#endif
         else continue;

         /* Allocate space for it */
         if (discovered_hosts.size >= discovered_hosts_allocated)
         {
            size_t allocated               = discovered_hosts_allocated;
            struct netplay_host *new_hosts = NULL;

            if (allocated == 0)
               allocated  = 2;
            else
               allocated *= 2;

            if (discovered_hosts.hosts)
               new_hosts  = (struct netplay_host *)
                  realloc(discovered_hosts.hosts, allocated * sizeof(struct
                  netplay_host));
            else
               /* Should be equivalent to realloc, but I don't trust screwy libcs */
               new_hosts = (struct netplay_host *)
                  malloc(allocated * sizeof(struct netplay_host));

            if (!new_hosts)
               return false;

            discovered_hosts.hosts     = new_hosts;
            discovered_hosts_allocated = allocated;
         }

         /* Get our host structure */
         host = &discovered_hosts.hosts[discovered_hosts.size++];

         /* Copy in the response */
         memset(host, 0, sizeof(struct netplay_host));
         host->addr    = their_addr;
         host->addrlen = addr_size;

         strlcpy(host->nick, ad_packet_buffer.nick, NETPLAY_HOST_STR_LEN);
         strlcpy(host->core, ad_packet_buffer.core, NETPLAY_HOST_STR_LEN);
         strlcpy(host->core_version, ad_packet_buffer.core_version,
            NETPLAY_HOST_STR_LEN);
         strlcpy(host->content, ad_packet_buffer.content,
            NETPLAY_HOST_LONGSTR_LEN);

         host->content_crc                  = 
            atoi(ad_packet_buffer.content_crc);
         host->nick[NETPLAY_HOST_STR_LEN-1] =
            host->core[NETPLAY_HOST_STR_LEN-1] =
            host->core_version[NETPLAY_HOST_STR_LEN-1] =
            host->content[NETPLAY_HOST_LONGSTR_LEN-1] = '\0';
      }
   }

   return true;
}
/**
 * netplay_pre_frame:
 * @netplay              : pointer to netplay object
 *
 * Pre-frame for Netplay.
 * Call this before running retro_run().
 *
 * Returns: true (1) if the frontend is cleared to emulate the frame, false (0)
 * if we're stalled or paused
 **/
bool netplay_pre_frame(netplay_t *netplay)
{
   bool sync_stalled;
   settings_t *settings  = config_get_ptr();

   retro_assert(netplay);

   if (settings->bools.netplay_public_announce)
   {
      reannounce++;
      if ((netplay->is_server || is_mitm) && (reannounce % 600 == 0))
         netplay_announce();
   }
   else
   {
      /* Make sure that if announcement is turned on mid-game, it gets announced */
      reannounce = -1;
   }

   /* FIXME: This is an ugly way to learn we're not paused anymore */
   if (netplay->local_paused)
      netplay_frontend_paused(netplay, false);

   if (netplay->quirks & NETPLAY_QUIRK_INITIALIZATION)
   {
      /* Are we ready now? */
      netplay_try_init_serialization(netplay);
   }

   if (netplay->is_server && !settings->bools.netplay_use_mitm_server)
   {
      /* Advertise our server */
      netplay_lan_ad_server(netplay);

      /* NAT traversal if applicable */
      if (netplay->nat_traversal &&
          !netplay->nat_traversal_task_oustanding &&
          netplay->nat_traversal_state.request_outstanding &&
          !netplay->nat_traversal_state.have_inet4)
      {
         struct timeval tmptv = {0};
         fd_set fds = netplay->nat_traversal_state.fds;
         if (socket_select(netplay->nat_traversal_state.nfds, &fds, NULL, NULL, &tmptv) > 0)
            natt_read(&netplay->nat_traversal_state);

#ifndef HAVE_SOCKET_LEGACY
         if (!netplay->nat_traversal_state.request_outstanding ||
             netplay->nat_traversal_state.have_inet4)
            netplay_announce_nat_traversal(netplay);
#endif
      }
   }

   sync_stalled = !netplay_sync_pre_frame(netplay);

   /* If we're disconnected, deinitialize */
   if (!netplay->is_server && !netplay->connections[0].active)
   {
      netplay_disconnect(netplay);
      return true;
   }

   if (sync_stalled ||
       ((!netplay->is_server || (netplay->connected_players>1)) &&
        (netplay->stall || netplay->remote_paused)))
   {
      /* We may have received data even if we're stalled, so run post-frame
       * sync */
      netplay_sync_post_frame(netplay, true);
      return false;
   }
   return true;
}
Exemple #19
0
bool netplay_ad_server(netplay_t *netplay, int ad_fd)
{
   fd_set fds;
   struct timeval tmp_tv = {0};
   struct sockaddr their_addr;
   socklen_t addr_size;
   rarch_system_info_t *info = NULL;
   size_t bufloc;

   if (!ad_packet_buffer)
   {
      ad_packet_buffer = (uint32_t *) malloc(AD_PACKET_MAX_SIZE);
      if (!ad_packet_buffer)
         return false;
   }

   /* Check for any ad queries */
   while (1)
   {
      FD_ZERO(&fds);
      FD_SET(ad_fd, &fds);
      if (socket_select(ad_fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0)
         break;
      if (!FD_ISSET(ad_fd, &fds))
         break;

      /* Somebody queried, so check that it's valid */
      if (recvfrom(ad_fd, (char*)ad_packet_buffer, AD_PACKET_MAX_SIZE, 0,
                   &their_addr, &addr_size) >= (ssize_t) (2*sizeof(uint32_t)))
      {
         /* Make sure it's a valid query */
         if (memcmp(ad_packet_buffer, "RANQ", 4))
            continue;

         /* For this version */
         if (ntohl(ad_packet_buffer[1]) != NETPLAY_PROTOCOL_VERSION)
            continue;

         runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &info);

         /* Now build our response */
         memset(ad_packet_buffer, 0, AD_PACKET_MAX_SIZE);
         memcpy(ad_packet_buffer, "RANS", 4);
         ad_packet_buffer[1] = htonl(NETPLAY_PROTOCOL_VERSION);
         ad_packet_buffer[2] = htonl(netplay->tcp_port);
         bufloc = 3;
         strncpy((char *) (ad_packet_buffer + bufloc),
                 PACKAGE_VERSION, AD_PACKET_STRING_SIZE);
         bufloc += AD_PACKET_STRING_WORDS;
         strncpy((char *) (ad_packet_buffer + bufloc),
                 netplay->nick, AD_PACKET_STRING_SIZE);
         bufloc += AD_PACKET_STRING_WORDS;
         if (info)
         {
            strncpy((char *) (ad_packet_buffer + bufloc),
                    info->info.library_name, AD_PACKET_STRING_SIZE);
            bufloc += AD_PACKET_STRING_WORDS;
            strncpy((char *) (ad_packet_buffer + bufloc),
                    info->info.library_version, AD_PACKET_STRING_SIZE);
            bufloc += AD_PACKET_STRING_WORDS;
            /* Blank content */
            bufloc += AD_PACKET_STRING_WORDS;
         }
         else
         {
            bufloc += 3*AD_PACKET_STRING_WORDS;
         }

         /* And send it */
         sendto(ad_fd, (const char*)ad_packet_buffer, bufloc*sizeof(uint32_t), 0,
                &their_addr, addr_size);
      }
   }

   return true;
}
/**
 * netplay_lan_ad_server
 *
 * Respond to any LAN ad queries that the netplay server has received.
 */
bool netplay_lan_ad_server(netplay_t *netplay)
{
   fd_set fds;
   struct timeval tmp_tv = {0};
   struct sockaddr their_addr;
   socklen_t addr_size;
   rarch_system_info_t *info = NULL;

   if (lan_ad_server_fd < 0 && !init_lan_ad_server_socket(netplay, RARCH_DEFAULT_PORT))
       return false;

   /* Check for any ad queries */
   while (1)
   {
      FD_ZERO(&fds);
      FD_SET(lan_ad_server_fd, &fds);
      if (socket_select(lan_ad_server_fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0)
         break;
      if (!FD_ISSET(lan_ad_server_fd, &fds))
         break;

      /* Somebody queried, so check that it's valid */
      addr_size = sizeof(their_addr);

      if (recvfrom(lan_ad_server_fd, (char*)&ad_packet_buffer,
            sizeof(struct ad_packet), 0, &their_addr, &addr_size) >=
            (ssize_t) (2*sizeof(uint32_t)))
      {
         char s[NETPLAY_HOST_STR_LEN];
         uint32_t content_crc         = 0;

         /* Make sure it's a valid query */
         if (memcmp((void *) &ad_packet_buffer, "RANQ", 4))
            continue;

         /* For this version */
         if (ntohl(ad_packet_buffer.protocol_version) !=
               NETPLAY_PROTOCOL_VERSION)
            continue;

         info              = runloop_get_system_info();

         /* Now build our response */
         content_crc = content_get_crc();

         memset(&ad_packet_buffer, 0, sizeof(struct ad_packet));
         memcpy(&ad_packet_buffer, "RANS", 4);

         ad_packet_buffer.protocol_version =
            htonl(NETPLAY_PROTOCOL_VERSION);
         ad_packet_buffer.port = htonl(netplay->tcp_port);
         strlcpy(ad_packet_buffer.retroarch_version, PACKAGE_VERSION,
            NETPLAY_HOST_STR_LEN);
         strlcpy(ad_packet_buffer.content, !string_is_empty(
                  path_basename(path_get(RARCH_PATH_BASENAME))) 
               ? path_basename(path_get(RARCH_PATH_BASENAME)) : "N/A",
               NETPLAY_HOST_LONGSTR_LEN);
         strlcpy(ad_packet_buffer.nick, netplay->nick, NETPLAY_HOST_STR_LEN);

         if (info)
         {
            strlcpy(ad_packet_buffer.core, info->info.library_name,
               NETPLAY_HOST_STR_LEN);
            strlcpy(ad_packet_buffer.core_version, info->info.library_version,
               NETPLAY_HOST_STR_LEN);
         }

         snprintf(s, sizeof(s), "%d", content_crc);
         strlcpy(ad_packet_buffer.content_crc, s,
            NETPLAY_HOST_STR_LEN);

         /* And send it */
         sendto(lan_ad_server_fd, (const char*)&ad_packet_buffer,
            sizeof(struct ad_packet), 0, &their_addr, addr_size);
      }
   }

   return true;
}
Exemple #21
0
/**
 * netplay_net_pre_frame:
 * @netplay              : pointer to netplay object
 *
 * Pre-frame for Netplay (normal version).
 **/
static bool netplay_net_pre_frame(netplay_t *netplay)
{
   retro_ctx_serialize_info_t serial_info;

   if (netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->self_ptr], netplay->self_frame_count))
   {
      serial_info.data_const = NULL;
      serial_info.data = netplay->buffer[netplay->self_ptr].state;
      serial_info.size = netplay->state_size;

      memset(serial_info.data, 0, serial_info.size);
      if ((netplay->quirks & NETPLAY_QUIRK_INITIALIZATION) || netplay->self_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)
         {
            /* Send this along to the other side */
            serial_info.data_const = netplay->buffer[netplay->self_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->stall_frames = 0;
      }

      /* If we can't transmit savestates, we must stall until the client is ready */
      if (!netplay->has_connection &&
          netplay->self_frame_count > 0 &&
          (netplay->quirks & (NETPLAY_QUIRK_NO_SAVESTATES|NETPLAY_QUIRK_NO_TRANSMISSION)))
         netplay->stall = RARCH_NETPLAY_STALL_NO_CONNECTION;
   }

   if (netplay->is_server && !netplay->has_connection)
   {
      fd_set fds;
      struct timeval tmp_tv = {0};
      int new_fd;
      struct sockaddr_storage their_addr;
      socklen_t addr_size;

      /* Check for a connection */
      FD_ZERO(&fds);
      FD_SET(netplay->fd, &fds);
      if (socket_select(netplay->fd + 1, &fds, NULL, NULL, &tmp_tv) > 0 &&
          FD_ISSET(netplay->fd, &fds))
      {
         addr_size = sizeof(their_addr);
         new_fd = accept(netplay->fd, (struct sockaddr*)&their_addr, &addr_size);
         if (new_fd < 0)
         {
            RARCH_ERR("%s\n", msg_hash_to_str(MSG_NETPLAY_FAILED));
            return true;
         }

         socket_close(netplay->fd);
         netplay->fd = new_fd;

#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
         {
            int flag = 1;
            if (setsockopt(netplay->fd, IPPROTO_TCP, TCP_NODELAY, (void*)&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(netplay->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

         /* Establish the connection */
         if (netplay_handshake(netplay))
         {
            netplay->has_connection = true;

            /* Send them the savestate */
            if (!(netplay->quirks & (NETPLAY_QUIRK_NO_SAVESTATES|NETPLAY_QUIRK_NO_TRANSMISSION)))
            {
               netplay->force_send_savestate = true;
            }
            else
            {
               /* Because the first frame isn't serialized, we're actually at
                * frame 1 */
               netplay->self_ptr = NEXT_PTR(netplay->self_ptr);
               netplay->self_frame_count = 1;
            }

            /* And expect the current frame from the other side */
            netplay->read_frame_count = netplay->other_frame_count = netplay->self_frame_count;
            netplay->read_ptr = netplay->other_ptr = netplay->self_ptr;

            /* Unstall if we were waiting for this */
            if (netplay->stall == RARCH_NETPLAY_STALL_NO_CONNECTION)
               netplay->stall = 0;

         }
         else
         {
            socket_close(netplay->fd);
            /* FIXME: Get in a state to accept another client */

         }
      }
   }

   netplay->can_poll = true;
   input_poll_net();

   return (netplay->stall != RARCH_NETPLAY_STALL_NO_CONNECTION);
}
int socket_wait_readable(struct mySocket *sock, struct timeval *timeout) {
	return socket_select(sock, timeout, 1, 0);
}
Exemple #23
0
/**
 * netplay_pre_frame_spectate:   
 * @netplay              : pointer to netplay object
 *
 * Pre-frame for Netplay (spectate mode version).
 **/
static void netplay_spectate_pre_frame(netplay_t *netplay)
{
   unsigned i;
   uint32_t *header;
   int new_fd, idx, bufsize;
   size_t header_size;
   struct sockaddr_storage their_addr;
   socklen_t addr_size;
   fd_set fds;
   struct timeval tmp_tv = {0};

   if (!np_is_server(netplay))
      return;

   FD_ZERO(&fds);
   FD_SET(netplay->fd, &fds);

   if (socket_select(netplay->fd + 1, &fds, NULL, NULL, &tmp_tv) <= 0)
      return;

   if (!FD_ISSET(netplay->fd, &fds))
      return;

   addr_size = sizeof(their_addr);
   new_fd = accept(netplay->fd, (struct sockaddr*)&their_addr, &addr_size);
   if (new_fd < 0)
   {
      RARCH_ERR("Failed to accept incoming spectator.\n");
      return;
   }

   idx = -1;
   for (i = 0; i < MAX_SPECTATORS; i++)
   {
      if (netplay->spectate.fds[i] == -1)
      {
         idx = i;
         break;
      }
   }

   /* No vacant client streams :( */
   if (idx == -1)
   {
      socket_close(new_fd);
      return;
   }

   if (!np_get_nickname(netplay, new_fd))
   {
      RARCH_ERR("Failed to get nickname from client.\n");
      socket_close(new_fd);
      return;
   }

   if (!np_send_nickname(netplay, new_fd))
   {
      RARCH_ERR("Failed to send nickname to client.\n");
      socket_close(new_fd);
      return;
   }

   header = np_bsv_header_generate(&header_size,
         np_impl_magic());

   if (!header)
   {
      RARCH_ERR("Failed to generate BSV header.\n");
      socket_close(new_fd);
      return;
   }

   bufsize = header_size;
   setsockopt(new_fd, SOL_SOCKET, SO_SNDBUF, (const char*)&bufsize,
         sizeof(int));

   if (!socket_send_all_blocking(new_fd, header, header_size))
   {
      RARCH_ERR("Failed to send header to client.\n");
      socket_close(new_fd);
      free(header);
      return;
   }

   free(header);
   netplay->spectate.fds[idx] = new_fd;

#ifndef HAVE_SOCKET_LEGACY
   np_log_connection(&their_addr, idx, netplay->other_nick);
#endif
}