Example #1
0
VALUE renet_connection_initialize(VALUE self, VALUE host, VALUE port, VALUE channels, VALUE download, VALUE upload)
{
  rb_funcall(mENet, rb_intern("initialize"), 0);
  Connection* connection;

  /* Now that we're releasing the GIL while waiting for enet_host_service 
     we need a lock to prevent potential segfaults if another thread tries
     to do an operation on same connection  */
  VALUE lock = rb_mutex_new();
  rb_iv_set(self, "@lock", lock); 
  rb_mutex_lock(lock);

  Data_Get_Struct(self, Connection, connection);
  Check_Type(host, T_STRING);
  if (enet_address_set_host(connection->address, StringValuePtr(host)) != 0)
  {
    rb_raise(rb_eStandardError, "Cannot set address");
  }
  connection->address->port = NUM2UINT(port);
  connection->channels = NUM2UINT(channels);
  connection->online = 0;
  connection->host = enet_host_create(NULL, 1, connection->channels, NUM2UINT(download), NUM2UINT(upload));
  if (connection->host == NULL)
  {
    rb_raise(rb_eStandardError, "Cannot create host");
  }
  rb_iv_set(self, "@total_sent_data", INT2FIX(0)); 
  rb_iv_set(self, "@total_received_data", INT2FIX(0));
  rb_iv_set(self, "@total_sent_packets", INT2FIX(0));
  rb_iv_set(self, "@total_received_packets", INT2FIX(0));

  rb_mutex_unlock(lock);
  return self;
}
Example #2
0
VALUE renet_connection_send_packet(VALUE self, VALUE data, VALUE flag, VALUE channel)
{
  Connection* connection;
  Data_Get_Struct(self, Connection, connection);
  VALUE lock = rb_iv_get(self, "@lock");
  rb_mutex_lock(lock);

  Check_Type(data, T_STRING);
  char* cdata = StringValuePtr(data);
  ENetPacket* packet;
  if (connection->online != 0)
  {
    if (flag == Qtrue)
    {
      packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, ENET_PACKET_FLAG_RELIABLE);
    }
    else
    {
      packet = enet_packet_create(cdata, RSTRING_LEN(data) + 1, 0);
    }
    enet_peer_send(connection->peer, NUM2UINT(channel), packet);
  }

  rb_mutex_unlock(lock);
  return Qnil;
}
Example #3
0
/* The core API functions for a connection: 
  renet_connection_connect
  renet_connection_disconnect
  renet_connection_send_packet
  renet_connection_send_queued_packets
  renet_connection_update
  renet_connection_use_compression
  renet_connection_online
*/
VALUE renet_connection_connect(VALUE self, VALUE timeout)
{
  Connection* connection;
  Data_Get_Struct(self, Connection, connection);
  VALUE lock = rb_iv_get(self, "@lock");
  rb_mutex_lock(lock);

  VALUE rv = Qfalse;

  if (connection->online == 0)
  {
    connection->peer = enet_host_connect(connection->host, connection->address, connection->channels, 0);    
      
    if (connection->peer == NULL)
    {
      rb_raise(rb_eStandardError, "Cannot connect to remote host");
    }
    
    if (service(self, connection, NUM2UINT(timeout)) > 0 && connection->event->type == ENET_EVENT_TYPE_CONNECT)
    {
      connection->online = 1;
      renet_connection_execute_on_connection(self);
      rv = Qtrue;
    }
    else
    {
      enet_peer_reset(connection->peer);
    }
  }

  rb_mutex_unlock(lock);
  return rv;
}
Example #4
0
VALUE renet_server_initialize(VALUE self, VALUE port, VALUE n_peers, VALUE channels, VALUE download, VALUE upload)
{
    rb_funcall(mENet, rb_intern("initialize"), 0);
    Server* server;
    Data_Get_Struct(self, Server, server);

    VALUE lock = rb_mutex_new();
    rb_iv_set(self, "@lock", lock); 
    rb_mutex_lock(lock);
    
    server->address->host = ENET_HOST_ANY;
    server->address->port = NUM2UINT(port);
    server->channels = NUM2UINT(channels);
    server->host = enet_host_create(server->address, NUM2UINT(n_peers), server->channels, NUM2UINT(download), NUM2UINT(upload));
    if (server->host == NULL)
    {
        rb_raise(rb_eStandardError, "Cannot create server");
    }
    rb_iv_set(self, "@total_sent_data", INT2FIX(0)); 
    rb_iv_set(self, "@total_received_data", INT2FIX(0));
    rb_iv_set(self, "@total_sent_packets", INT2FIX(0));
    rb_iv_set(self, "@total_received_packets", INT2FIX(0));

    rb_mutex_unlock(lock);
    
    return self;
}
Example #5
0
VALUE renet_server_send_queued_packets(VALUE self)
{
    Server* server;
    Data_Get_Struct(self, Server, server);
    VALUE lock = rb_iv_get(self, "@lock");
    rb_mutex_lock(lock);
    enet_host_flush(server->host);
    rb_mutex_unlock(lock);
    return Qnil;
}
Example #6
0
void renet_connection_execute_on_disconnection(VALUE self)
{
  VALUE method = rb_iv_get(self, "@on_disconnection");
  if (method != Qnil)
  {
    VALUE lock = rb_iv_get(self, "@lock");
    rb_mutex_unlock(lock);
    rb_funcall(method, rb_intern("call"), 0);
    rb_mutex_lock(lock);
  }
}
Example #7
0
VALUE renet_server_disconnect_client(VALUE self, VALUE peer_id)
{
    Server* server;
    Data_Get_Struct(self, Server, server);
    VALUE lock = rb_iv_get(self, "@lock");
    rb_mutex_lock(lock);
    enet_peer_disconnect_now(&(server->host->peers[NUM2UINT(peer_id)]), 0);
    renet_server_execute_on_disconnection(self, peer_id);
    rb_mutex_unlock(lock);
    return Qtrue;
}
Example #8
0
void renet_server_execute_on_connection(VALUE self, VALUE peer_id, VALUE ip)
{
    VALUE method = rb_iv_get(self, "@on_connection");
    if (method != Qnil)
    {
        VALUE lock = rb_iv_get(self, "@lock");
        rb_mutex_unlock(lock);
        rb_funcall(method, rb_intern("call"), 2, peer_id, ip);
        rb_mutex_lock(lock);
    }
}
Example #9
0
static void grpc_ruby_init_threads() {
  // Avoid calling into ruby library (when creating threads here)
  // in gpr_once_init. In general, it appears to be unsafe to call
  // into the ruby library while holding a non-ruby mutex, because a gil yield
  // could end up trying to lock onto that same mutex and deadlocking.
  rb_mutex_lock(bg_thread_init_rb_mu);
  if (!bg_thread_init_done) {
    grpc_rb_event_queue_thread_start();
    grpc_rb_channel_polling_thread_start();
    bg_thread_init_done = 1;
  }
  rb_mutex_unlock(bg_thread_init_rb_mu);
}
Example #10
0
VALUE
rb_xthread_monitor_exit(VALUE self)
{
  xthread_monitor_t *mon;
  VALUE th = rb_thread_current();
  
  GetXThreadMonitorPtr(self, mon);

  XTHREAD_MONITOR_CHECK_OWNER(self);
  mon->count--;
  if(mon->count == 0) {
    mon->owner = Qnil;
    rb_mutex_unlock(mon->mutex);
  }
}
Example #11
0
VALUE renet_connection_send_queued_packets(VALUE self)
{
  Connection* connection;
  Data_Get_Struct(self, Connection, connection);
  VALUE lock = rb_iv_get(self, "@lock");
  rb_mutex_lock(lock);

  if (connection->online != 0)
  {
    enet_host_flush(connection->host);
  }

  rb_mutex_unlock(lock);
  return Qnil;
}
Example #12
0
void renet_connection_execute_on_packet_receive(VALUE self, ENetPacket * const packet, enet_uint8 channelID)
{
  VALUE method  = rb_iv_get(self, "@on_packet_receive");
  VALUE data    = rb_str_new((char const *)packet->data, packet->dataLength);
  /* marshal data and then destroy packet 
     if we don't do this now the packet might become invalid before we get
     back and we'd get a segfault when we attempt to destroy */
  enet_packet_destroy(packet); 

  if (method != Qnil)
  {
    VALUE lock = rb_iv_get(self, "@lock");
    rb_mutex_unlock(lock);
    rb_funcall(method, rb_intern("call"), 2, data, UINT2NUM(channelID));
    rb_mutex_lock(lock);
  }
}
Example #13
0
VALUE renet_server_use_compression(VALUE self, VALUE flag)
{
    Server* server;
    Data_Get_Struct(self, Server, server);
    VALUE lock = rb_iv_get(self, "@lock");
    rb_mutex_lock(lock);
    if (flag == Qtrue)
    {
        enet_host_compress_with_range_coder(server->host);
    }
    else
    {
        enet_host_compress(server->host, NULL);
    }
    rb_mutex_unlock(lock);
    return Qnil;
}
Example #14
0
VALUE renet_connection_use_compression(VALUE self, VALUE flag)
{
  Connection* connection;
  Data_Get_Struct(self, Connection, connection);
  VALUE lock = rb_iv_get(self, "@lock");
  rb_mutex_lock(lock);

  if (flag == Qtrue)
  {
    enet_host_compress_with_range_coder(connection->host);
  }
  else
  {
    enet_host_compress(connection->host, NULL);
  }

  rb_mutex_unlock(lock);
  return Qnil;
}
Example #15
0
VALUE renet_connection_disconnect(VALUE self, VALUE timeout)
{
  Connection* connection;
  Data_Get_Struct(self, Connection, connection);
  VALUE lock = rb_iv_get(self, "@lock");
  rb_mutex_lock(lock);

  VALUE rv = Qfalse;

  if (connection->online == 0)
  {
    rv = Qtrue;
  }
  else
  {      
    connection->online = 0;
    enet_peer_disconnect(connection->peer, 0);

    while (service(self, connection, NUM2UINT(timeout)) > 0)
    {
      switch (connection->event->type)
      {
      case ENET_EVENT_TYPE_NONE:
        break;
      case ENET_EVENT_TYPE_CONNECT:
        break;
      case ENET_EVENT_TYPE_RECEIVE:
        enet_packet_destroy (connection->event->packet);
        break;
      case ENET_EVENT_TYPE_DISCONNECT:
        rv = Qtrue;
        break;
      }
      if (rv == Qtrue)
      {
        break;
      }
    }
    if (rv != Qtrue) { enet_peer_disconnect_now(connection->peer, 0); }
  }
  rb_mutex_unlock(lock);
  return rv;
}
Example #16
0
VALUE
rb_mutex_sleep(VALUE self, VALUE timeout)
{
    time_t beg, end;
    struct timeval t;

    if (!NIL_P(timeout)) {
        t = rb_time_interval(timeout);
    }
    rb_mutex_unlock(self);
    beg = time(0);
    if (NIL_P(timeout)) {
	rb_ensure(rb_mutex_sleep_forever, Qnil, rb_mutex_lock, self);
    }
    else {
	rb_ensure(rb_mutex_wait_for, (VALUE)&t, rb_mutex_lock, self);
    }
    end = time(0) - beg;
    return INT2FIX(end);
}
Example #17
0
VALUE renet_server_broadcast_packet(VALUE self, VALUE data, VALUE flag, VALUE channel)
{
    Server* server;
    Data_Get_Struct(self, Server, server);
    VALUE lock = rb_iv_get(self, "@lock");
    rb_mutex_lock(lock);
    Check_Type(data, T_STRING);
    char* cdata = StringValuePtr(data);
    ENetPacket* packet;
    if (flag == Qtrue)
    {
        packet = enet_packet_create(cdata, RSTRING_LEN(data), ENET_PACKET_FLAG_RELIABLE);
    }
    else
    {
        packet = enet_packet_create(cdata, RSTRING_LEN(data), 0);
    }
    enet_host_broadcast(server->host, NUM2UINT(channel), packet);
    rb_mutex_unlock(lock);
    return Qnil;
}
Example #18
0
static VALUE
mutex_sleep(VALUE self, SEL sel, int argc, VALUE *argv)
{
    VALUE timeout;
    rb_scan_args(argc, argv, "01", &timeout);

    rb_mutex_unlock(self, 0);
    
    time_t beg, end;
    beg = time(0);

    if (timeout == Qnil) {
	rb_thread_sleep_forever();	
    }
    else {
	struct timeval t = rb_time_interval(timeout);
	rb_thread_wait_for(t);
    }

    end = time(0) - beg;
    return INT2FIX(end);        
}
Example #19
0
void rho_ruby_unlock_mutex(VALUE val)
{
    rb_mutex_unlock(val);
}
Example #20
0
VALUE renet_server_update(VALUE self, VALUE timeout)
{
  Server* server;
  Data_Get_Struct(self, Server, server);
  VALUE lock = rb_iv_get(self, "@lock");
  rb_mutex_lock(lock);
  int peer_id;
  
  /* wait up to timeout milliseconds for a packet */
  if (service(self, server, NUM2UINT(timeout)) > 0)
  {
    do
    {
      switch (server->event->type)
      {
        case ENET_EVENT_TYPE_NONE:
          break;
        
        case ENET_EVENT_TYPE_CONNECT:
          server->n_clients += 1;
          enet_address_get_host_ip(&(server->event->peer->address), server->conn_ip, 20);
          peer_id = (int)(server->event->peer - server->host->peers);
          renet_server_execute_on_connection(self, INT2NUM(peer_id), rb_str_new2(server->conn_ip));
          break;

        case ENET_EVENT_TYPE_RECEIVE:
          peer_id = (int)(server->event->peer - server->host->peers);
          renet_server_execute_on_packet_receive(self, INT2NUM(peer_id), server->event->packet, server->event->channelID);
          break;
       
        case ENET_EVENT_TYPE_DISCONNECT:
          server->n_clients -= 1;
          peer_id = (int)(server->event->peer - server->host->peers);
          server->event->peer->data = NULL;
          renet_server_execute_on_disconnection(self, INT2NUM(peer_id));
          break;
      }
    }
    while (service(self, server, 0) > 0);
  }

  /* we are unlocking now because it's important to unlock before going 
    back into ruby land (which rb_funcall will do). If we don't then an
    exception can leave the locks in an inconsistent state */
  rb_mutex_unlock(lock);

  {
    VALUE total = rb_iv_get(self, "@total_sent_data");
    VALUE result = rb_funcall( total
                             , rb_intern("+")
                             , 1
                             , UINT2NUM(server->host->totalSentData));
    rb_iv_set(self, "@total_sent_data", result); 
    server->host->totalSentData = 0;
  }

  {
    VALUE total = rb_iv_get(self, "@total_received_data");
    VALUE result = rb_funcall( total
                             , rb_intern("+")
                             , 1
                             , UINT2NUM(server->host->totalReceivedData));
    rb_iv_set(self, "@total_received_data", result);
    server->host->totalReceivedData = 0;
  }

  {
    VALUE total = rb_iv_get(self, "@total_sent_packets");
    VALUE result = rb_funcall( total
                             , rb_intern("+")
                             , 1
                             , UINT2NUM(server->host->totalSentPackets));
    rb_iv_set(self, "@total_sent_packets", result);
    server->host->totalSentPackets = 0;
  }

  {
    VALUE total = rb_iv_get(self, "@total_received_packets");
    VALUE result = rb_funcall( total
                             , rb_intern("+")
                             , 1
                             , UINT2NUM(server->host->totalReceivedPackets));
    rb_iv_set(self, "@total_received_packets", result);
    server->host->totalReceivedPackets = 0;
  }
  
  return Qtrue;
}
Example #21
0
VALUE renet_connection_update(VALUE self, VALUE timeout)
{
  Connection* connection;
  Data_Get_Struct(self, Connection, connection);
  VALUE lock = rb_iv_get(self, "@lock");
  rb_mutex_lock(lock);

  VALUE rv = Qfalse;

  if (connection->online != 0)
  {
    /* wait up to timeout milliseconds for a packet */
    if (service(self, connection, NUM2UINT(timeout)) > 0)
    {
      do
      {
        switch (connection->event->type)
        {
        case ENET_EVENT_TYPE_NONE:
          break;
        case ENET_EVENT_TYPE_CONNECT:
          break;
        case ENET_EVENT_TYPE_RECEIVE:
          renet_connection_execute_on_packet_receive(self, connection->event->packet, connection->event->channelID);
          break;
        case ENET_EVENT_TYPE_DISCONNECT:
          connection->online = 0;
          renet_connection_execute_on_disconnection(self);
          break;
        }
      }
      /* Do not use a timeout for subsequent services or we could get stuck 
         here forever */
      while ((connection->online != 0) && (service(self, connection, 0) > 0));
    }

    rv = Qtrue;
  }

  /* we are unlocking now because it's important to unlock before going 
    back into ruby land (which rb_funcall will do). If we don't then an
    exception can leave the locks in an inconsistent state */
  rb_mutex_unlock(lock);

  if (rv == Qtrue)
  {
    {
      VALUE total = rb_iv_get(self, "@total_sent_data");
      VALUE result = rb_funcall( total
                               , rb_intern("+")
                               , 1
                               , UINT2NUM(connection->host->totalSentData));
      rb_iv_set(self, "@total_sent_data", result); 
      connection->host->totalSentData = 0;
    }

    {
      VALUE total = rb_iv_get(self, "@total_received_data");
      VALUE result = rb_funcall( total
                               , rb_intern("+")
                               , 1
                               , UINT2NUM(connection->host->totalReceivedData));
      rb_iv_set(self, "@total_received_data", result);
      connection->host->totalReceivedData = 0;
    }

    {
      VALUE total = rb_iv_get(self, "@total_sent_packets");
      VALUE result = rb_funcall( total
                               , rb_intern("+")
                               , 1
                               , UINT2NUM(connection->host->totalSentPackets));
      rb_iv_set(self, "@total_sent_packets", result);
      connection->host->totalSentPackets = 0;
    }

    {
      VALUE total = rb_iv_get(self, "@total_received_packets");
      VALUE result = rb_funcall( total
                               , rb_intern("+")
                               , 1
                               , UINT2NUM(connection->host->totalReceivedPackets));
      rb_iv_set(self, "@total_received_packets", result);
      connection->host->totalReceivedPackets = 0;
    }
  }
  
  return rv;
}