Exemplo n.º 1
0
/** Eventloop callback called when a new connection is received on a listening Socket.
 *
 * This function accept()s the connection, and creates a SocketInt to wrap
 * the underlying system socket. It then runs the user-supplied callback
 * (passed to socket_server_new() when creating the listening Socket) on this
 * new object, passing it the handle (passed to socket_server_new( too))
 *
 * \param source source from which the event was received (e.g., an OComm Channel)
 * \param handle pointer to opaque data passed when creating the listening Socket
 */
static void
on_client_connect(SockEvtSource* source, void* handle)
{
  (void)source; // FIXME: Check why source parameter is unused
  char host[ADDRLEN], serv[SERVLEN];
  size_t namesize;
  *host = 0;
  *serv = 0;

  socklen_t cli_len;
  SocketInt* self = (SocketInt*)handle;
  SocketInt* newSock = socket_initialize(NULL);
  cli_len = sizeof(newSock->servAddr.sa_stor);
  newSock->sockfd = accept(self->sockfd,
                &newSock->servAddr.sa,
                 &cli_len);

  if (newSock->sockfd < 0) {
    o_log(O_LOG_ERROR, "socket(%s): Error on accept: %s\n",
          self->name, strerror(errno));
    oml_free(newSock);
    return;
  }

  /* XXX: Duplicated somewhat with socket_in_new and s_connect */
  if (!getnameinfo(&newSock->servAddr.sa, cli_len,
        host, ADDRLEN, serv, SERVLEN,
        NI_NUMERICHOST|NI_NUMERICSERV)) {
    namesize =  strlen(host) + strlen(serv) + 3 + 1;
    newSock->name = oml_realloc(newSock->name, namesize);
    snprintf(newSock->name, namesize, "[%s]:%s", host, serv);

  } else {
    namesize =  strlen(host) + 4 + 10 + 1; /* XXX: 10 is arbitrarily chosen for the
                                              number of characters in sockfd's decimal
                                              representation */
    newSock->name = oml_realloc(newSock->name, namesize);
    snprintf(newSock->name, namesize, "%s-io:%d", self->name, newSock->sockfd);
    o_log(O_LOG_WARN, "socket(%s): Error resolving new client source, defaulting to %s: %s\n",
        self->name, newSock->name, strerror(errno));
  }

  if (self->connect_callback) {
    self->connect_callback((Socket*)newSock, self->connect_handle);
  }
}
Exemplo n.º 2
0
/** Create OSocket objects bound to name and service.
 *
 * This function binds the newly-created socket, but doesn't listen on it just
 * yet.  If name resolves to more than one AF, several sockets are created,
 * linked through their `next' field.
 *
 * \param name name of the object, used for debugging
 * \param node address or name to listen on; defaults to all if NULL
 * \param service symbolic name or port number of the service to bind to
 * \param is_tcp true if TCP, false for UDP XXX: This should be more generic
 * \return a pointer to a linked list of SocketInt objects, cast as Socket
 *
 * \see getaddrinfo(3)
 */
Socket*
socket_in_new(const char* name, const char* node, const char* service, int is_tcp)
{
  SocketInt *self = NULL, *list = NULL;
  char nameserv[SOCKNAMELEN], *namestr = NULL;
  size_t namestr_size;
  struct addrinfo hints, *results, *rp;
  int ret;

  *nameserv = 0;
  memset(&hints, 0, sizeof(struct addrinfo));

  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP; /* FIXME: We should check self->is_tcp */
  hints.ai_flags= AI_PASSIVE;
  int val = 1;

  if((ret=getaddrinfo(node, service, &hints, &results))) {
      o_log(O_LOG_ERROR, "socket(%s): Error resolving %s:%s: %s\n",
          name, node, service, gai_strerror(ret));
      return NULL;
  }

  for (rp = results; rp != NULL; rp = rp->ai_next) {
    sockaddr_get_name((sockaddr_t*)rp->ai_addr, rp->ai_addrlen, nameserv, SOCKNAMELEN);
    namestr_size = strlen(name) + strlen(nameserv + 2);
    namestr = oml_realloc(namestr, namestr_size);
    snprintf(namestr, namestr_size, "%s-%s", name, nameserv);
    o_log(O_LOG_DEBUG, "socket(%s): Binding to %s (AF %d, proto %d)\n",
        name, nameserv, rp->ai_family, rp->ai_protocol);

    if (NULL == (self = (SocketInt*)socket_new(namestr, is_tcp))) {
      o_log(O_LOG_WARN, "socket(%s): Could allocate Socket to listen on %s: %s\n",
          self->name, nameserv, strerror(errno));

    } else if(0 > (self->sockfd =
          socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol))) {
      /* It's OK if some AFs fail, we check that in the end */
      o_log(O_LOG_DEBUG, "socket(%s): Could not create socket to listen on %s: %s\n",
          self->name, nameserv, strerror(errno));
      socket_free((Socket*)self);

    } else if(0 != setsockopt(self->sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(int))){
      o_log(O_LOG_WARN, "socket(%s): Could not set option SO_REUSEADDR on socket to listen on %s: %s\n",
          self->name, nameserv, strerror(errno));
      close(self->sockfd);
      /* XXX: Not optimal: we could reuse the Socket */
      socket_free((Socket*)self);

    } else if (0 != bind(self->sockfd, rp->ai_addr, rp->ai_addrlen)) {
      o_log(O_LOG_WARN, "socket(%s): Error binding socket to listen on %s: %s\n",
          self->name, nameserv, strerror(errno));
      close(self->sockfd);
      /* XXX: Not optimal: we could reuse the Socket */
      socket_free((Socket*)self);

    } else {
      /* The last connected AFs (hence less important according to GAI) are
       * now at the front, but it's not a big deal as we treat them all
       * equally (i.e, we're going to listen on them all */
      self->next = (Socket*)list;
      list = self;
      self = NULL;
    }

  }

  if (namestr) { oml_free(namestr); }
  freeaddrinfo(results);

  if (NULL == list) {
    o_log(O_LOG_ERROR, "socket(%s): Could not create any socket to listen on port %s\n",
        name, service);
  }

  return (Socket*)list;
}
Exemplo n.º 3
0
/** Search a Database's registered DbTables for one matchng the given schema.
 *
 * If none is found, the table is created. If one is found, but the schema
 * differs, try to append a number to the name (up to MAX_TABLE_RENAME), create
 * that table, and update the schema.
 *
 * If the table search/creation is successful, the returned DbTable is already
 * added to the list of the Database.
 *
 * \param database Database to search
 * \param schema schema structure for the table to add
 * \return a newly created DbTable for that table, or NULL on error
 *
 * \see MAX_TABLE_RENAME, database_create_table
 */
DbTable*
database_find_or_create_table(Database *database, struct schema *schema)
{
  if (database == NULL) return NULL;
  if (schema == NULL) return NULL;

  DbTable *table = NULL;
  struct schema *s = schema_copy(schema);
  int i = 1;
  int diff = 0, tnlen;

  tnlen = strlen(schema->name);

  do {
    table = database_find_table (database, s->name);

    if (table) {
      diff = schema_diff (s, table->schema);
      if (!diff) {
        if(database->semantic){
          if (database->table_create (database, table, 0)) {
              logerror ("%s: Couldn't create table '%s'\n", database->name, schema->name);
            }
        }
        schema_free(s);
        return table;

      } else if (diff == -1) {
        logerror ("%s: Schema error table '%s'\n", database->name, s->name);
        logdebug (" One of the server schema %p or the client schema %p is probably NULL\n", s, table->schema);

      } else if (diff > 0) {
        logdebug ("%s: Schema differ for table '%s', at or after column %d\n",
            database->name, s->name, diff);
      }

      if (i == 1) {
        /* First time we need to increase the size */
        /* Add space for 2 characters and null byte, that is up to '_9', with MAX_TABLE_RENAME = 10 */
        s->name = oml_realloc(s->name, tnlen + 3);
        strncpy(s->name, schema->name, tnlen);
      }
      snprintf(&s->name[tnlen], 3, "_%d", ++i);
    }

  } while(table && diff && (i < MAX_TABLE_RENAME));

  if (table && diff) {
    logerror ("%s: Too many (>%d) tables named '%s_x', giving up. Please use the rename attribute of <mp /> tags.\n",
      database->name, MAX_TABLE_RENAME, schema->name);
    schema_free(s);
    return NULL;
  }

  if(i>1) {
    /* We had to change the table name*/
    logwarn("%s: Creating table '%s' for new stream '%s' with incompatible schema\n", database->name, s->name, schema->name);
    oml_free(schema->name);
    schema->name = oml_strndup(s->name, tnlen+3);
  }
  schema_free(s);

  /* No table by that name exists, so we create it */
  table = database_create_table (database, schema);
  if (!table)
    return NULL;
  if (database->table_create (database, table, 0)) {
    logerror ("%s: Couldn't create table '%s'\n", database->name, schema->name);
    /* Unlink the table from the experiment's list */
    DbTable* t = database->first_table;
    if (t == table)
      database->first_table = t->next;
    else {
      while (t && t->next != table)
        t = t->next;
      if (t && t->next)
        t->next = t->next->next;
    }
    database_table_free (database, table);
    return NULL;
  }
  return table;
}