static int init_ssl_socket( pn_ssl_t *ssl )
{
  if (ssl->ssl) return 0;
  if (!ssl->domain) return -1;

  ssl->ssl = SSL_new(ssl->domain->ctx);
  if (!ssl->ssl) {
    _log_error( "SSL socket setup failure.\n" );
    return -1;
  }

  // store backpointer to pn_ssl_t in SSL object:
  SSL_set_ex_data(ssl->ssl, ssl_ex_data_index, ssl);

#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
  if (ssl->peer_hostname && ssl->domain->mode == PN_SSL_MODE_CLIENT) {
    SSL_set_tlsext_host_name(ssl->ssl, ssl->peer_hostname);
  }
#endif

  // restore session, if available
  if (ssl->session_id) {
    pn_ssl_session_t *ssn = ssn_cache_find( ssl->domain, ssl->session_id );
    if (ssn) {
      _log( ssl, "Restoring previous session id=%s\n", ssn->id );
      int rc = SSL_set_session( ssl->ssl, ssn->session );
      if (rc != 1) {
        _log( ssl, "Session restore failed, id=%s\n", ssn->id );
      }
      LL_REMOVE( ssl->domain, ssn_cache, ssn );
      ssl_session_free( ssn );
    }
  }

  // now layer a BIO over the SSL socket
  ssl->bio_ssl = BIO_new(BIO_f_ssl());
  if (!ssl->bio_ssl) {
    _log_error( "BIO setup failure.\n" );
    return -1;
  }
  (void)BIO_set_ssl(ssl->bio_ssl, ssl->ssl, BIO_NOCLOSE);

  // create the "lower" BIO "pipe", and attach it below the SSL layer
  if (!BIO_new_bio_pair(&ssl->bio_ssl_io, 0, &ssl->bio_net_io, 0)) {
    _log_error( "BIO setup failure.\n" );
    return -1;
  }
  SSL_set_bio(ssl->ssl, ssl->bio_ssl_io, ssl->bio_ssl_io);

  if (ssl->domain->mode == PN_SSL_MODE_SERVER) {
    SSL_set_accept_state(ssl->ssl);
    BIO_set_ssl_mode(ssl->bio_ssl, 0);  // server mode
    _log( ssl, "Server SSL socket created.\n" );
  } else {      // client mode
    SSL_set_connect_state(ssl->ssl);
    BIO_set_ssl_mode(ssl->bio_ssl, 1);  // client mode
    _log( ssl, "Client SSL socket created.\n" );
  }
  return 0;
}
int pn_ssl_domain_set_peer_authentication(pn_ssl_domain_t *domain,
                                          const pn_ssl_verify_mode_t mode,
                                          const char *trusted_CAs)
{
  if (!domain) return -1;

  switch (mode) {
  case PN_SSL_VERIFY_PEER:
  case PN_SSL_VERIFY_PEER_NAME:

    if (!domain->has_ca_db) {
      _log_error("Error: cannot verify peer without a trusted CA configured.\n"
                 "       Use pn_ssl_domain_set_trusted_ca_db()\n");
      return -1;
    }

    if (domain->mode == PN_SSL_MODE_SERVER) {
      // openssl requires that server connections supply a list of trusted CAs which is
      // sent to the client
      if (!trusted_CAs) {
        _log_error("Error: a list of trusted CAs must be provided.\n");
        return -1;
      }
      if (!domain->has_certificate) {
      _log_error("Error: Server cannot verify peer without configuring a certificate.\n"
                 "       Use pn_ssl_domain_set_credentials()\n");
      }

      if (domain->trusted_CAs) free(domain->trusted_CAs);
      domain->trusted_CAs = pn_strdup( trusted_CAs );
      STACK_OF(X509_NAME) *cert_names;
      cert_names = SSL_load_client_CA_file( domain->trusted_CAs );
      if (cert_names != NULL)
        SSL_CTX_set_client_CA_list(domain->ctx, cert_names);
      else {
        _log_error("Error: Unable to process file of trusted CAs: %s\n", trusted_CAs);
        return -1;
      }
    }

    SSL_CTX_set_verify( domain->ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                        verify_callback);
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
    SSL_CTX_set_verify_depth(domain->ctx, 1);
#endif
    break;

  case PN_SSL_ANONYMOUS_PEER:   // hippie free love mode... :)
    SSL_CTX_set_verify( domain->ctx, SSL_VERIFY_NONE, NULL );
    break;

  default:
    _log_error( "Invalid peer authentication mode given.\n" );
    return -1;
  }

  domain->verify_mode = mode;
  return 0;
}
int pn_ssl_domain_set_trusted_ca_db(pn_ssl_domain_t *domain,
                                    const char *certificate_db)
{
  if (!domain) return -1;

  // certificates can be either a file or a directory, which determines how it is passed
  // to SSL_CTX_load_verify_locations()
  struct stat sbuf;
  if (stat( certificate_db, &sbuf ) != 0) {
    _log_error("stat(%s) failed: %s\n", certificate_db, strerror(errno));
    return -1;
  }

  const char *file;
  const char *dir;
  if (S_ISDIR(sbuf.st_mode)) {
    dir = certificate_db;
    file = NULL;
  } else {
    dir = NULL;
    file = certificate_db;
  }

  if (SSL_CTX_load_verify_locations( domain->ctx, file, dir ) != 1) {
    _log_ssl_error( "SSL_CTX_load_verify_locations( %s ) failed\n", certificate_db);
    return -1;
  }

  domain->has_ca_db = true;

  return 0;
}
static void
_execute_correct(const gchar *testcase, Checks checks, const gchar *user_data)
{
  if (!_execute(testcase, checks, user_data))
    {
      _log_error("expected the subject to succeed, but it failed");
      _tests_failed = 1;
    }
}
static void
_execute_failing(const gchar *testcase, Checks checks, const gchar *user_data)
{
  if (_execute(testcase, checks, user_data))
    {
      _log_error("expected the subject to fail, but it succeeded");
      _tests_failed = 1;
    }
}
int pn_ssl_domain_allow_unsecured_client(pn_ssl_domain_t *domain)
{
  if (!domain) return -1;
  if (domain->mode != PN_SSL_MODE_SERVER) {
    _log_error("Cannot permit unsecured clients - not a server.\n");
    return -1;
  }
  domain->allow_unsecured = true;
  return 0;
}
// log an error and dump the SSL error stack
static void _log_ssl_error( const char *fmt, ...)
{
  char buf[128];        // see "man ERR_error_string_n()"
  va_list ap;

  if (fmt) {
    va_start(ap, fmt);
    vfprintf(stderr, fmt, ap);
    va_end(ap);
  }

  unsigned long err = ERR_get_error();
  while (err) {
    ERR_error_string_n(err, buf, sizeof(buf));
    _log_error("%s\n", buf);
    err = ERR_get_error();
  }
}
Beispiel #8
0
SEXP _est_gen_Q_C( SEXP spYdelt,
  		   	SEXP spZ,
  		   	SEXP spX,
  		   	SEXP spMaf,
		   	SEXP spParNull)
{
	// int nUsed0, nTotal0;
	// CFmVector::StatCache( &nTotal0, &nUsed0 );
	// int nUsed1, nTotal1;
	// CFmMatrix::StatCache( &nTotal1, &nUsed1 );
	// Rprintf( "Enter C Range, Vec.count=%d, Mat.count=%d\n", nTotal0, nTotal1);

	CFmMatrix* pFmYDelt = getMatrixData(spYdelt);
	CFmMatrix* pFmZ     = getMatrixData(spZ);
	CFmMatrix* pFmX     = getMatrixData(spX);
	CFmVector* pFmMaf   = getVectorData(spMaf);
	CFmVector* pFmParNull = getVectorData(spParNull);

	SEXP ret;
	try
	{
		ret = Xest_gen_Q_C( pFmYDelt, pFmZ, pFmX, pFmMaf, pFmParNull);
	}
    catch(const char* str)
    {
        _log_error( _HI_, "Exception=%s", str);
        return( R_NilValue );
    }

	destroy( pFmYDelt );
	destroy( pFmZ );
	destroy( pFmX );
	destroy( pFmMaf );
	destroy( pFmParNull );

	// CFmVector::StatCache( &nTotal0, &nUsed0 );
	// CFmMatrix::StatCache( &nTotal1, &nUsed1 );
	// Rprintf( "Leave C Range, Vec.count=%d, Mat.count=%d\n", nTotal0, nTotal1);

	return(ret);
}
// take data from the network, and pass it into SSL.  Attempt to read decrypted data from
// SSL socket and pass it to the application.
static ssize_t process_input_ssl( pn_io_layer_t *io_layer, const char *input_data, size_t available)
{
  pn_ssl_t *ssl = (pn_ssl_t *)io_layer->context;
  if (ssl->ssl == NULL && init_ssl_socket(ssl)) return PN_ERR;

  _log( ssl, "process_input_ssl( data size=%d )\n",available );

  ssize_t consumed = 0;
  bool work_pending;
  bool shutdown_input = (available == 0);  // caller is closed

  do {
    work_pending = false;

    // Write to network bio as much as possible, consuming bytes/available

    if (available > 0) {
      int written = BIO_write( ssl->bio_net_io, input_data, available );
      if (written > 0) {
        input_data += written;
        available -= written;
        consumed += written;
        ssl->read_blocked = false;
        work_pending = (available > 0);
        _log( ssl, "Wrote %d bytes to BIO Layer, %d left over\n", written, available );
      }
    } else if (shutdown_input) {
      // lower layer (caller) has closed.  Close the WRITE side of the BIO.  This will cause
      // an EOF to be passed to SSL once all pending inbound data has been consumed.
      _log( ssl, "Lower layer closed - shutting down BIO write side\n");
      (void)BIO_shutdown_wr( ssl->bio_net_io );
      shutdown_input = false;
    }

    // Read all available data from the SSL socket

    if (!ssl->ssl_closed && ssl->in_count < ssl->in_size) {
      int read = BIO_read( ssl->bio_ssl, &ssl->inbuf[ssl->in_count], ssl->in_size - ssl->in_count );
      if (read > 0) {
        _log( ssl, "Read %d bytes from SSL socket for app\n", read );
        _log_clear_data( ssl, &ssl->inbuf[ssl->in_count], read );
        ssl->in_count += read;
        work_pending = true;
      } else {
        if (!BIO_should_retry(ssl->bio_ssl)) {
          int reason = SSL_get_error( ssl->ssl, read );
          switch (reason) {
          case SSL_ERROR_ZERO_RETURN:
            // SSL closed cleanly
            _log(ssl, "SSL connection has closed\n");
            start_ssl_shutdown(ssl);  // KAG: not sure - this may not be necessary
            ssl->ssl_closed = true;
            break;
          default:
            // unexpected error
            return (ssize_t)ssl_failed(ssl);
          }
        } else {
          if (BIO_should_write( ssl->bio_ssl )) {
            ssl->write_blocked = true;
            _log(ssl, "Detected write-blocked\n");
          }
          if (BIO_should_read( ssl->bio_ssl )) {
            ssl->read_blocked = true;
            _log(ssl, "Detected read-blocked\n");
          }
        }
      }
    }

    // write incoming data to app layer

    if (!ssl->app_input_closed) {
      char *data = ssl->inbuf;
      if (ssl->in_count > 0 || ssl->ssl_closed) {  /* if ssl_closed, send 0 count */
        pn_io_layer_t *io_next = ssl->io_layer->next;
        ssize_t consumed = io_next->process_input( io_next, data, ssl->in_count);
        if (consumed > 0) {
          ssl->in_count -= consumed;
          data += consumed;
          work_pending = true;
          _log( ssl, "Application consumed %d bytes from peer\n", (int) consumed );
        } else if (consumed < 0) {
          _log(ssl, "Application layer closed its input, error=%d (discarding %d bytes)\n",
               (int) consumed, (int)ssl->in_count);
          ssl->in_count = 0;    // discard any pending input
          ssl->app_input_closed = consumed;
          if (ssl->app_output_closed && ssl->out_count == 0) {
            // both sides of app closed, and no more app output pending:
            start_ssl_shutdown(ssl);
          }
        } else {
          // app did not consume any bytes, must be waiting for a full frame
          if (ssl->in_count == ssl->in_size) {
            // but the buffer is full, not enough room for a full frame.
            // can we grow the buffer?
            uint32_t max_frame = pn_transport_get_max_frame(ssl->transport);
            if (!max_frame) max_frame = ssl->in_size * 2;  // no limit
            if (ssl->in_size < max_frame) {
              // no max frame limit - grow it.
              char *newbuf = (char *)malloc( max_frame );
              if (newbuf) {
                ssl->in_size *= max_frame;
                memmove( newbuf, ssl->inbuf, ssl->in_count );
                free( ssl->inbuf );
                ssl->inbuf = newbuf;
              }
              work_pending = true;  // can we get more input?
            } else {
              // can't gather any more input, but app needs more?
              // This is a bug - since SSL can buffer up to max-frame,
              // the application _must_ have enough data to process.  If
              // this is an oversized frame, the app _must_ handle it
              // by returning an error code to SSL.
              _log_error("Error: application unable to consume input.\n");
            }
          }
        }
      }
      if (ssl->in_count > 0 && data != ssl->inbuf)
        memmove( ssl->inbuf, data, ssl->in_count );
    }

  } while (work_pending);

  //_log(ssl, "ssl_closed=%d in_count=%d app_input_closed=%d app_output_closed=%d\n",
  //     ssl->ssl_closed, ssl->in_count, ssl->app_input_closed, ssl->app_output_closed );

  // PROTON-82: Instead, close the input side as soon as we've completed enough of the SSL
  // shutdown handshake to send the close_notify.  We're not requiring the response, as
  // some implementations never reply.
  // ---
  // tell transport our input side is closed if the SSL socket cannot be read from any
  // longer, AND any pending input has been written up to the application (or the
  // application is closed)
  //if (ssl->ssl_closed && ssl->app_input_closed) {
  //  consumed = ssl->app_input_closed;
  //}
  if (ssl->app_input_closed && (SSL_get_shutdown(ssl->ssl) & SSL_SENT_SHUTDOWN) ) {
    consumed = ssl->app_input_closed;
    ssl->io_layer->process_input = process_input_done;
  }
  _log(ssl, "process_input_ssl() returning %d\n", (int) consumed);
  return consumed;
}
pn_ssl_domain_t *pn_ssl_domain( pn_ssl_mode_t mode )
{
  if (!ssl_initialized) {
    ssl_initialized = 1;
    SSL_library_init();
    SSL_load_error_strings();
    OpenSSL_add_all_algorithms();
    ssl_ex_data_index = SSL_get_ex_new_index( 0, (void *) "org.apache.qpid.proton.ssl",
                                              NULL, NULL, NULL);
  }

  pn_ssl_domain_t *domain = (pn_ssl_domain_t *) calloc(1, sizeof(pn_ssl_domain_t));
  if (!domain) return NULL;

  domain->ref_count = 1;
  domain->mode = mode;
  switch(mode) {
  case PN_SSL_MODE_CLIENT:
    domain->ctx = SSL_CTX_new(TLSv1_client_method());
    if (!domain->ctx) {
      _log_ssl_error( "Unable to initialize OpenSSL context.\n");
      free(domain);
      return NULL;
    }
    break;

  case PN_SSL_MODE_SERVER:
    domain->ctx = SSL_CTX_new(SSLv23_server_method());
    if (!domain->ctx) {
      _log_ssl_error("Unable to initialize OpenSSL context.\n");
      free(domain);
      return NULL;
    }
    SSL_CTX_set_options(domain->ctx, SSL_OP_NO_SSLv2);  // v2 is insecure
    break;

  default:
    _log_error("Invalid valid for pn_ssl_mode_t: %d\n", mode);
    free(domain);
    return NULL;
  }

  // by default, allow anonymous ciphers so certificates are not required 'out of the box'
  if (!SSL_CTX_set_cipher_list( domain->ctx, CIPHERS_ANONYMOUS )) {
    _log_ssl_error("Failed to set cipher list to %s\n", CIPHERS_ANONYMOUS);
    pn_ssl_domain_free(domain);
    return NULL;
  }

  // ditto: by default do not authenticate the peer (can be done by SASL).
  if (pn_ssl_domain_set_peer_authentication( domain, PN_SSL_ANONYMOUS_PEER, NULL )) {
    pn_ssl_domain_free(domain);
    return NULL;
  }

  DH *dh = get_dh2048();
  if (dh) {
    SSL_CTX_set_tmp_dh(domain->ctx, dh);
    DH_free(dh);
    SSL_CTX_set_options(domain->ctx, SSL_OP_SINGLE_DH_USE);
  }

  return domain;
}
// Certificate chain verification callback: return 1 if verified,
// 0 if remote cannot be verified (fail handshake).
//
static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
  if (!preverify_ok || X509_STORE_CTX_get_error_depth(ctx) != 0)
    // already failed, or not at peer cert in chain
    return preverify_ok;

  X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
  SSL *ssn = (SSL *) X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
  if (!ssn) {
    _log_error("Error: unexpected error - SSL session info not available for peer verify!\n");
    return 0;  // fail connection
  }

  pn_ssl_t *ssl = (pn_ssl_t *)SSL_get_ex_data(ssn, ssl_ex_data_index);
  if (!ssl) {
    _log_error("Error: unexpected error - SSL context info not available for peer verify!\n");
    return 0;  // fail connection
  }

  if (ssl->domain->verify_mode != PN_SSL_VERIFY_PEER_NAME) return preverify_ok;
  if (!ssl->peer_hostname) {
    _log_error("Error: configuration error: PN_SSL_VERIFY_PEER_NAME configured, but no peer hostname set!\n");
    return 0;  // fail connection
  }

  _log( ssl, "Checking identifying name in peer cert against '%s'\n", ssl->peer_hostname);

  bool matched = false;

  /* first check any SubjectAltName entries, as per RFC2818 */
  GENERAL_NAMES *sans = (GENERAL_NAMES *) X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
  if (sans) {
    int name_ct = sk_GENERAL_NAME_num( sans );
    int i;
    for (i = 0; !matched && i < name_ct; ++i) {
      GENERAL_NAME *name = sk_GENERAL_NAME_value( sans, i );
      if (name->type == GEN_DNS) {
        ASN1_STRING *asn1 = name->d.dNSName;
        if (asn1 && asn1->data && asn1->length) {
          unsigned char *str;
          int len = ASN1_STRING_to_UTF8( &str, asn1 );
          if (len >= 0) {
            _log( ssl, "SubjectAltName (dns) from peer cert = '%.*s'\n", len, str );
            matched = match_dns_pattern( ssl->peer_hostname, (const char *)str, len );
            OPENSSL_free( str );
          }
        }
      }
    }
    GENERAL_NAMES_free( sans );
  }

  /* if no general names match, try the CommonName from the subject */
  X509_NAME *name = X509_get_subject_name(cert);
  int i = -1;
  while (!matched && (i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0) {
    X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, i);
    ASN1_STRING *name_asn1 = X509_NAME_ENTRY_get_data(ne);
    if (name_asn1) {
      unsigned char *str;
      int len = ASN1_STRING_to_UTF8( &str, name_asn1);
      if (len >= 0) {
        _log( ssl, "commonName from peer cert = '%.*s'\n", len, str );
        matched = match_dns_pattern( ssl->peer_hostname, (const char *)str, len );
        OPENSSL_free(str);
      }
    }
  }

  if (!matched) {
    _log( ssl, "Error: no name matching %s found in peer cert - rejecting handshake.\n",
          ssl->peer_hostname);
    preverify_ok = 0;
#ifdef X509_V_ERR_APPLICATION_VERIFICATION
    X509_STORE_CTX_set_error( ctx, X509_V_ERR_APPLICATION_VERIFICATION );
#endif
  } else {
    _log( ssl, "Name from peer cert matched - peer is valid.\n" );
  }
  return preverify_ok;
}
Beispiel #12
0
/* Process each event emitted by the protocol engine */
static void dispatcher(pn_handler_t *handler, pn_event_t *event, pn_event_type_t type)
{
	protocolState_t *ps = PROTOCOL_STATE(handler);
	const configSettings_t *cfg = ps->config;

	//DBGPRINTF("omamqp1: Event received: %s\n", pn_event_type_name(type));

	switch (type) {

	case PN_LINK_REMOTE_OPEN:
	    DBGPRINTF("omamqp1: Message bus opened link.\n");
	    break;

	case PN_DELIVERY:
	    // has the message been delivered to the message bus?
	    if (ps->delivery) {
	        assert(ps->delivery == pn_event_delivery(event));
	        if (pn_delivery_updated(ps->delivery)) {
	            rsRetVal result = RS_RET_IDLE;
	            uint64_t rs = pn_delivery_remote_state(ps->delivery);
	            switch (rs) {
	            case PN_ACCEPTED:
	                DBGPRINTF("omamqp1: Message ACCEPTED by message bus\n");
	                result = RS_RET_OK;
	                break;
	            case PN_REJECTED:
	              dbgprintf("omamqp1: message bus rejected log message: invalid message - dropping\n");
	                // message bus considers this a 'bad message'. Cannot be redelivered.
	                // Likely a configuration error. Drop the message by returning OK
	                result = RS_RET_OK;
	                break;
	            case PN_RELEASED:
	            case PN_MODIFIED:
		// the message bus cannot accept the message.  This may be temporary - retry
		// up to maxRetries before dropping
	                if (++ps->retries >= cfg->maxRetries) {
	                  dbgprintf("omamqp1: message bus failed to accept message - dropping\n");
	                  result = RS_RET_OK;
	                } else {
	                  dbgprintf("omamqp1: message bus cannot accept message, retrying\n");
	                  result = RS_RET_SUSPENDED;
	                }
	                break;
	            case PN_RECEIVED:
	                // not finished yet, wait for next delivery update
	                break;
	            default:
	                // no other terminal states defined, so ignore anything else
	                dbgprintf("omamqp1: unknown delivery state=0x%lX, assuming message accepted\n",
	                          (unsigned long) pn_delivery_remote_state(ps->delivery));
	                result = RS_RET_OK;
	                break;
	            }

	            if (result != RS_RET_IDLE) {
	                // the command is complete
	                threadIPC_t *ipc = ps->ipc;
	                pthread_mutex_lock(&ipc->lock);
	                assert(ipc->command == COMMAND_SEND);
	                ipc->result = result;
	                ipc->command = COMMAND_DONE;
	                pthread_cond_signal(&ipc->condition);
	                pthread_mutex_unlock(&ipc->lock);
	                pn_delivery_settle(ps->delivery);
	                ps->delivery = NULL;
	                if (result == RS_RET_OK) {
	                  ps->retries = 0;
	                }
	            }
	        }
	    }
	    break;


	case PN_CONNECTION_BOUND:
	    if (!cfg->bDisableSASL) {
	        // force use of SASL, even allowing PLAIN authentication
	        pn_sasl_t *sasl = pn_sasl(pn_event_transport(event));
#if PN_VERSION_MAJOR == 0 && PN_VERSION_MINOR >= 10
	        pn_sasl_set_allow_insecure_mechs(sasl, true);
#else
	        // proton version <= 0.9 only supports PLAIN authentication
	        const char *user = cfg->username
	            ? (char *)cfg->username
	            : pn_url_get_username(cfg->url);
	        if (user) {
	            pn_sasl_plain(sasl, user, (cfg->password
	                                       ? (char *) cfg->password
	                                       : pn_url_get_password(cfg->url)));
	        }
#endif
	    }
	    if (cfg->idleTimeout) {
	        // configured as seconds, set as milliseconds
	        pn_transport_set_idle_timeout(pn_event_transport(event),
	                                      cfg->idleTimeout * 1000);
	    }
	    break;

	case PN_CONNECTION_UNBOUND:
	    DBGPRINTF("omamqp1: cleaning up connection resources\n");
	    pn_connection_release(pn_event_connection(event));
	    ps->conn = NULL;
	    ps->sender = NULL;
	    ps->delivery = NULL;
	    break;


	case PN_TRANSPORT_ERROR:
	    {
	        // TODO: if auth failure, does it make sense to retry???
	        pn_transport_t *tport = pn_event_transport(event);
	        pn_condition_t *cond = pn_transport_condition(tport);
	        if (pn_condition_is_set(cond)) {
	            _log_error("transport failure", cond);
	        }
	        dbgprintf("omamqp1: network transport failed, reconnecting...\n");
	        // the protocol thread will attempt to reconnect if it is not
	        // being shut down
	    }
	    break;

	default:
	    break;
	}
}
Beispiel #13
0
// this function reads a file for "," separated values and creates a matrix object from it
int CFmDataFrame::Load(const char* filename, bool bRowName, bool bColName)
{
    _log_debug(_HI_, "CFmDataFrame::Load:%s, bRowName=%d, bColName=%d", filename, bRowName, bColName);

    FILE* fp = fopen( filename, "rt");
    if (fp==NULL)
    {
        _log_error(_HI_, "The file can not be opened(%s)", filename);
        return(ERR_OPEN_FILE);
    }

    char aLine[MAX_LINE_WIDTH+1]={0};
    if( fgets( aLine, MAX_LINE_WIDTH, fp ) == NULL)
    {
        _log_error( _HI_, "Failed to read a line (%s)", filename);

        fclose(fp);
        return(ERR_READ_FILE);
    }

    CFmVectorStr vctRowNames(0);
    CFmVectorStr vctColNames(0);
    int col_size = 0;

    // count how many elements in the first lines
    const char seps1[] = ",\t\n\r";

    char* running = Strdup (aLine);
    char* runnptr = running;
    char* token = _strsep((char**)&running, seps1 );
    while(token)
    {
		if(strlen(token)!=0)
		{
			vctColNames.Put( token);
		    col_size++;
        }

    	token = _strsep( (char**)&running, seps1 );
    }

    Free(runnptr);

    _log_debug(_HI_, "CFmDataFrame::Load:  col_size: %d", col_size);

    CFmVector tmpRow(col_size, 0.0);
    if (bRowName && !bColName)
        tmpRow.Resize(col_size-1);

    int nMaxRows = 20;
    int nMaxCols = tmpRow.GetLength();
    m_nNumCols = tmpRow.GetLength();
    m_nNumRows = 0;

    AllocMemory( nMaxRows, nMaxCols );

    if (!bColName)
    {
        if (!bRowName)
        {
            m_nNumCols = col_size;
            for (int i=0; i<col_size; i++)
                Set(0, i, vctColNames[i]);
        }
        else
        {
            m_nNumCols = col_size-1;
            for (int i=1; i<col_size+1; i++)
                Set(0, i-1, vctColNames[i]);
            vctRowNames.Put( vctColNames[0] );
        }

        m_nNumRows++;
    }

    CFmVectorStr vctTmpRow(0);
    while(!feof(fp))
    {
        if( fgets( aLine, MAX_LINE_WIDTH, fp ) == NULL)
            break;

        char* running = Strdup (aLine);

        vctTmpRow.Reset(0);
        char* token = _strsep( &running, seps1 );
        int nNonEmty = 0;

        while(token)
        {
            if (strlen(token)!=0 &&
                strncmp(token, "\n", 1)!=0 &&
                strncmp(token, "\r", 1)!=0 &&
                strncmp(token, "\t", 1)!=0)
                nNonEmty ++;
            vctTmpRow.Put(token);
            token = _strsep( &running, seps1 );
        }

        Free(running);
        if (nNonEmty==0)
            break;

        m_nNumRows++;
        if (m_nNumRows >= m_nMaxRows )
            AllocMemory( m_nNumRows+20, m_nMaxCols );

        if (!bRowName)
        {
            for (int i=0; i<col_size && i<vctTmpRow.GetLength(); i++)
                Set( m_nNumRows-1, i,  vctTmpRow[i] );
        }
        else
        {
            for (int i=1; i<col_size+1 && i<vctTmpRow.GetLength(); i++)
            {
                Set( m_nNumRows-1, i-1,  vctTmpRow[i] );
            }

            vctRowNames.Put( vctTmpRow[0]);
        }
    }

    fclose(fp);

	CFmNewTemp refNew;
    if (bRowName)
        m_pRowNames = new (refNew) CFmVectorStr( &vctRowNames );

    if (bColName)
        m_pColNames = new (refNew) CFmVectorStr( &vctColNames );

    _log_debug(_HI_, "CFmDataFrame::Load:%d,%d", m_nNumRows, m_nNumCols);

    return(0);
}