Example #1
0
int pn_messenger_subscribe(pn_messenger_t *messenger, const char *source)
{
  int len = strlen(source);
  if (len >= 3 && source[0] == '/' && source[1] == '/' && source[2] == '~') {
    pn_listener_t *lnr = pn_messenger_isource(messenger, source);
    if (lnr) {
      return 0;
    } else {
      return pn_error_format(messenger->error, PN_ERR,
                             "unable to subscribe to source: %s (%s)", source,
                             pn_driver_error(messenger->driver));
    }
  } else if (len >= 2 && source[0] == '/' && source[1] == '/') {
    pn_link_t *src = pn_messenger_source(messenger, source);
    if (src) {
      return 0;
    } else {
      return pn_error_format(messenger->error, PN_ERR,
                             "unable to subscribe to source: %s (%s)", source,
                             pn_driver_error(messenger->driver));
    }
  } else {
    return 0;
  }
}
Example #2
0
static uint8_t pn_type2code(pn_encoder_t *encoder, pn_type_t type)
{
  switch (type)
  {
  case PN_NULL: return PNE_NULL;
  case PN_BOOL: return PNE_BOOLEAN;
  case PN_UBYTE: return PNE_UBYTE;
  case PN_BYTE: return PNE_BYTE;
  case PN_USHORT: return PNE_USHORT;
  case PN_SHORT: return PNE_SHORT;
  case PN_UINT: return PNE_UINT;
  case PN_INT: return PNE_INT;
  case PN_CHAR: return PNE_UTF32;
  case PN_FLOAT: return PNE_FLOAT;
  case PN_LONG: return PNE_LONG;
  case PN_TIMESTAMP: return PNE_MS64;
  case PN_DOUBLE: return PNE_DOUBLE;
  case PN_DECIMAL32: return PNE_DECIMAL32;
  case PN_DECIMAL64: return PNE_DECIMAL64;
  case PN_DECIMAL128: return PNE_DECIMAL128;
  case PN_UUID: return PNE_UUID;
  case PN_ULONG: return PNE_ULONG;
  case PN_BINARY: return PNE_VBIN32;
  case PN_STRING: return PNE_STR32_UTF8;
  case PN_SYMBOL: return PNE_SYM32;
  case PN_LIST: return PNE_LIST32;
  case PN_ARRAY: return PNE_ARRAY32;
  case PN_MAP: return PNE_MAP32;
  case PN_DESCRIBED: return PNE_DESCRIPTOR;
  default:
    return pn_error_format(encoder->error, PN_ERR, "not a value type: %u\n", type);
  }
}
Example #3
0
pn_socket_t pn_connect(pn_io_t *io, const char *host, const char *port)
{
  struct addrinfo *addr;
  int code = getaddrinfo(host, port, NULL, &addr);
  if (code) {
    pn_error_format(io->error, PN_ERR, "getaddrinfo(%s, %s): %s", host, port, gai_strerror(code));
    return PN_INVALID_SOCKET;
  }

  pn_socket_t sock = pn_create_socket(addr->ai_family);
  if (sock == PN_INVALID_SOCKET) {
    pn_i_error_from_errno(io->error, "pn_create_socket");
    return PN_INVALID_SOCKET;
  }

  pn_configure_sock(io, sock);

  if (connect(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
    if (errno != EINPROGRESS) {
      pn_i_error_from_errno(io->error, "connect");
      freeaddrinfo(addr);
      close(sock);
      return PN_INVALID_SOCKET;
    }
  }

  freeaddrinfo(addr);

  return sock;
}
Example #4
0
int pni_win32_error(pn_error_t *error, const char *msg, HRESULT code)
{
  // Error code can be from GetLastError or WSAGetLastError,
  char err[1024] = {0};
  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
                FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, code, 0, (LPSTR)&err, sizeof(err), NULL);
  return pn_error_format(error, PN_ERR, "%s: %s", msg, err);
}
int pn_i_error_from_errno(pn_error_t *error, const char *msg)
{
  char err[1024];
  pn_i_strerror(errno, err, 1024);
  int code = PN_ERR;
  if (errno == EINTR)
      code = PN_INTR;
  return pn_error_format(error, code, "%s: %s", msg, err);
}
Example #6
0
int pn_messenger_recv(pn_messenger_t *messenger, int n)
{
  if (!messenger) return PN_ARG_ERR;
  if (!messenger->listeners && !messenger->size)
    return pn_error_format(messenger->error, PN_STATE_ERR, "no valid sources");
  messenger->credit += n;
  pn_messenger_flow(messenger);
  return pn_messenger_sync(messenger, pn_messenger_rcvd);
}
Example #7
0
pn_socket_t pn_listen(pn_io_t *io, const char *host, const char *port)
{
  struct addrinfo *addr;
  int code = getaddrinfo(host, amqp_service(port), NULL, &addr);
  if (code) {
    pn_error_format(io->error, PN_ERR, "getaddrinfo(%s, %s): %s\n", host, port, gai_strerror(code));
    return INVALID_SOCKET;
  }

  pn_socket_t sock = pni_create_socket(addr->ai_family);
  if (sock == INVALID_SOCKET) {
    pni_win32_error(io->error, "pni_create_socket", WSAGetLastError());
    return INVALID_SOCKET;
  }
  ensure_unique(io, sock);

  bool optval = 1;
  if (setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char *) &optval,
                 sizeof(optval)) == -1) {
    pni_win32_error(io->error, "setsockopt", WSAGetLastError());
    closesocket(sock);
    return INVALID_SOCKET;
  }

  if (bind(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
    pni_win32_error(io->error, "bind", WSAGetLastError());
    freeaddrinfo(addr);
    closesocket(sock);
    return INVALID_SOCKET;
  }
  freeaddrinfo(addr);

  if (listen(sock, 50) == -1) {
    pni_win32_error(io->error, "listen", WSAGetLastError());
    closesocket(sock);
    return INVALID_SOCKET;
  }

  if (io->iocp->selector) {
    iocpdesc_t *iocpd = pni_iocpdesc_create(io->iocp, sock, false);
    if (!iocpd) {
      pn_i_error_from_errno(io->error, "register");
      closesocket(sock);
      return INVALID_SOCKET;
    }
    pni_iocpdesc_start(iocpd);
  }

  return sock;
}
Example #8
0
// unrecoverable SSL failure occured, notify transport and generate error code.
static int ssl_failed(pn_ssl_t *ssl)
{
    SSL_set_shutdown(ssl->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
  ssl->ssl_closed = true;
  ssl->app_input_closed = ssl->app_output_closed = PN_ERR;
  // fake a shutdown so the i/o processing code will close properly
  SSL_set_shutdown(ssl->ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
  // try to grab the first SSL error to add to the failure log
  char buf[128] = "Unknown error.";
  unsigned long ssl_err = ERR_get_error();
  if (ssl_err) {
    ERR_error_string_n( ssl_err, buf, sizeof(buf) );
  }
  _log_ssl_error(NULL);    // spit out any remaining errors to the log file
  return pn_error_format( ssl->transport->error, PN_ERR, "SSL Failure: %s", buf );
}
Example #9
0
int pn_messenger_put(pn_messenger_t *messenger, pn_message_t *msg)
{
  if (!messenger) return PN_ARG_ERR;
  if (!msg) return pn_error_set(messenger->error, PN_ARG_ERR, "null message");
  outward_munge(messenger, msg);
  const char *address = pn_message_get_address(msg);
  pn_link_t *sender = pn_messenger_target(messenger, address);
  if (!sender)
    return pn_error_format(messenger->error, PN_ERR,
                           "unable to send to address: %s (%s)", address,
                           pn_driver_error(messenger->driver));
  // XXX: proper tag
  char tag[8];
  void *ptr = &tag;
  uint64_t next = messenger->next_tag++;
  *((uint32_t *) ptr) = next;
  pn_delivery(sender, pn_dtag(tag, 8));
  size_t size = 1024;
  // XXX: max message size
  while (size < 16*1024) {
    char encoded[size];
    int err = pn_message_encode(msg, encoded, &size);
    if (err == PN_OVERFLOW) {
      size *= 2;
    } else if (err) {
      return err;
    } else {
      ssize_t n = pn_send(sender, encoded, size);
      if (n < 0) {
        return n;
      } else {
        pn_advance(sender);
        pn_messenger_tsync(messenger, false_pred, 0);
        return 0;
      }
    }
  }

  return PN_ERR;
}
Example #10
0
pn_socket_t pn_listen(pn_io_t *io, const char *host, const char *port)
{
  struct addrinfo *addr;
  int code = getaddrinfo(host, port, NULL, &addr);
  if (code) {
    pn_error_format(io->error, PN_ERR, "getaddrinfo(%s, %s): %s\n", host, port, gai_strerror(code));
    return PN_INVALID_SOCKET;
  }

  pn_socket_t sock = pn_create_socket(addr->ai_family);
  if (sock == PN_INVALID_SOCKET) {
    pn_i_error_from_errno(io->error, "pn_create_socket");
    return PN_INVALID_SOCKET;
  }

  int optval = 1;
  if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {
    pn_i_error_from_errno(io->error, "setsockopt");
    close(sock);
    return PN_INVALID_SOCKET;
  }

  if (bind(sock, addr->ai_addr, addr->ai_addrlen) == -1) {
    pn_i_error_from_errno(io->error, "bind");
    freeaddrinfo(addr);
    close(sock);
    return PN_INVALID_SOCKET;
  }

  freeaddrinfo(addr);

  if (listen(sock, 50) == -1) {
    pn_i_error_from_errno(io->error, "listen");
    close(sock);
    return PN_INVALID_SOCKET;
  }

  return sock;
}
Example #11
0
pn_socket_t pn_accept(pn_io_t *io, pn_socket_t listen_sock, char *name, size_t size)
{
  struct sockaddr_in addr = {0};
  addr.sin_family = AF_INET;
  socklen_t addrlen = sizeof(addr);
  iocpdesc_t *listend = pni_iocpdesc_map_get(io->iocp, listen_sock);
  pn_socket_t accept_sock;

  if (listend)
    accept_sock = pni_iocp_end_accept(listend, (struct sockaddr *) &addr, &addrlen, &io->wouldblock, io->error);
  else {
    // User supplied socket
    accept_sock = accept(listen_sock, (struct sockaddr *) &addr, &addrlen);
    if (accept_sock == INVALID_SOCKET)
      pni_win32_error(io->error, "sync accept", WSAGetLastError());
  }

  if (accept_sock == INVALID_SOCKET)
    return accept_sock;

  int code = getnameinfo((struct sockaddr *) &addr, addrlen, io->host, NI_MAXHOST,
                         io->serv, NI_MAXSERV, 0);
  if (code)
    code = getnameinfo((struct sockaddr *) &addr, addrlen, io->host, NI_MAXHOST,
                       io->serv, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
  if (code) {
    pn_error_format(io->error, PN_ERR, "getnameinfo: %s\n", gai_strerror(code));
    pn_close(io, accept_sock);
    return INVALID_SOCKET;
  } else {
    pn_configure_sock(io, accept_sock);
    snprintf(name, size, "%s:%s", io->host, io->serv);
    if (listend) {
      pni_iocpdesc_start(pni_iocpdesc_map_get(io->iocp, accept_sock));
    }
    return accept_sock;
  }
}
Example #12
0
pn_socket_t pn_connect(pn_io_t *io, const char *hostarg, const char *port)
{
  // convert "0.0.0.0" to "127.0.0.1" on Windows for outgoing sockets
  const char *host = strcmp("0.0.0.0", hostarg) ? hostarg : "127.0.0.1";

  struct addrinfo *addr;
  int code = getaddrinfo(host, amqp_service(port), NULL, &addr);
  if (code) {
    pn_error_format(io->error, PN_ERR, "getaddrinfo(%s, %s): %s", host, port, gai_strerror(code));
    return INVALID_SOCKET;
  }

  pn_socket_t sock = pni_create_socket(addr->ai_family);
  if (sock == INVALID_SOCKET) {
    pni_win32_error(io->error, "proton pni_create_socket", WSAGetLastError());
    freeaddrinfo(addr);
    return INVALID_SOCKET;
  }

  ensure_unique(io, sock);
  pn_configure_sock(io, sock);

  if (io->iocp->selector) {
    return pni_iocp_begin_connect(io->iocp, sock, addr, io->error);
  } else {
    if (connect(sock, addr->ai_addr, addr->ai_addrlen) != 0) {
      if (WSAGetLastError() != WSAEWOULDBLOCK) {
	pni_win32_error(io->error, "connect", WSAGetLastError());
	freeaddrinfo(addr);
	closesocket(sock);
	return INVALID_SOCKET;
      }
    }

    freeaddrinfo(addr);
    return sock;
  }
}
Example #13
0
pn_socket_t pn_accept(pn_io_t *io, pn_socket_t socket, char *name, size_t size)
{
  struct sockaddr_in addr = {0};
  addr.sin_family = AF_UNSPEC;
  socklen_t addrlen = sizeof(addr);
  pn_socket_t sock = accept(socket, (struct sockaddr *) &addr, &addrlen);
  if (sock == PN_INVALID_SOCKET) {
    pn_i_error_from_errno(io->error, "accept");
    return sock;
  } else {
    int code;
    if ((code = getnameinfo((struct sockaddr *) &addr, addrlen, io->host, MAX_HOST, io->serv, MAX_SERV, 0))) {
      pn_error_format(io->error, PN_ERR, "getnameinfo: %s\n", gai_strerror(code));
      if (close(sock) == -1)
        pn_i_error_from_errno(io->error, "close");
      return PN_INVALID_SOCKET;
    } else {
      pn_configure_sock(io, sock);
      snprintf(name, size, "%s:%s", io->host, io->serv);
      return sock;
    }
  }
}
Example #14
0
int pn_messenger_get(pn_messenger_t *messenger, pn_message_t *msg)
{
  if (!messenger) return PN_ARG_ERR;

  for (int i = 0; i < messenger->size; i++) {
    pn_connector_t *ctor = messenger->connectors[i];
    pn_connection_t *conn = pn_connector_connection(ctor);

    pn_delivery_t *d = pn_work_head(conn);
    while (d) {
      if (pn_readable(d)) {
        // XXX: buf size, eof, etc
        char buf[1024];
        pn_link_t *l = pn_link(d);
        ssize_t n = pn_recv(l, buf, 1024);
        pn_settle(d);
        if (n < 0) return n;
        if (msg) {
          int err = pn_message_decode(msg, buf, n);
          if (err) {
            return pn_error_format(messenger->error, err, "error decoding message: %s",
                                 pn_message_error(msg));
          } else {
            return 0;
          }
        } else {
          return 0;
        }
      }
      d = pn_work_next(d);
    }
  }

  // XXX: need to drain credit before returning EOS

  return PN_EOS;
}
Example #15
0
static int pni_encoder_enter(void *ctx, pn_data_t *data, pni_node_t *node)
{
  pn_encoder_t *encoder = (pn_encoder_t *) ctx;
  pni_node_t *parent = pn_data_node(data, node->parent);
  int err;
  pn_atom_t *atom = &node->atom;
  uint8_t code;
  conv_t c;

  /** In an array we don't write the code before each element, only the first. */
  if (pn_is_in_array(data, parent, node)) {
    code = pn_type2code(encoder, parent->type);
    if (pn_is_first_in_array(data, parent, node)) {
      err = pn_encoder_writef8(encoder, code);
      if (err) return err;
    }
  } else {
    code = pn_node2code(encoder, node);
    err = pn_encoder_writef8(encoder, code);
    if (err) return err;
  }

  switch (code) {
  case PNE_DESCRIPTOR:
  case PNE_NULL:
  case PNE_TRUE:
  case PNE_FALSE: return 0;
  case PNE_BOOLEAN: return pn_encoder_writef8(encoder, atom->u.as_bool);
  case PNE_UBYTE: return pn_encoder_writef8(encoder, atom->u.as_ubyte);
  case PNE_BYTE: return pn_encoder_writef8(encoder, atom->u.as_byte);
  case PNE_USHORT: return pn_encoder_writef16(encoder, atom->u.as_ushort);
  case PNE_SHORT: return pn_encoder_writef16(encoder, atom->u.as_short);
  case PNE_UINT0: return 0;
  case PNE_SMALLUINT: return pn_encoder_writef8(encoder, atom->u.as_uint);
  case PNE_UINT: return pn_encoder_writef32(encoder, atom->u.as_uint);
  case PNE_SMALLINT: return pn_encoder_writef8(encoder, atom->u.as_int);
  case PNE_INT: return pn_encoder_writef32(encoder, atom->u.as_int);
  case PNE_UTF32: return pn_encoder_writef32(encoder, atom->u.as_char);
  case PNE_ULONG: return pn_encoder_writef64(encoder, atom->u.as_ulong);
  case PNE_SMALLULONG: return pn_encoder_writef8(encoder, atom->u.as_ulong);
  case PNE_LONG: return pn_encoder_writef64(encoder, atom->u.as_long);
  case PNE_SMALLLONG: return pn_encoder_writef8(encoder, atom->u.as_long);
  case PNE_MS64: return pn_encoder_writef64(encoder, atom->u.as_timestamp);
  case PNE_FLOAT: c.f = atom->u.as_float; return pn_encoder_writef32(encoder, c.i);
  case PNE_DOUBLE: c.d = atom->u.as_double; return pn_encoder_writef64(encoder, c.l);
  case PNE_DECIMAL32: return pn_encoder_writef32(encoder, atom->u.as_decimal32);
  case PNE_DECIMAL64: return pn_encoder_writef64(encoder, atom->u.as_decimal64);
  case PNE_DECIMAL128: return pn_encoder_writef128(encoder, atom->u.as_decimal128.bytes);
  case PNE_UUID: return pn_encoder_writef128(encoder, atom->u.as_uuid.bytes);
  case PNE_VBIN8: return pn_encoder_writev8(encoder, &atom->u.as_bytes);
  case PNE_VBIN32: return pn_encoder_writev32(encoder, &atom->u.as_bytes);
  case PNE_STR8_UTF8: return pn_encoder_writev8(encoder, &atom->u.as_bytes);
  case PNE_STR32_UTF8: return pn_encoder_writev32(encoder, &atom->u.as_bytes);
  case PNE_SYM8: return pn_encoder_writev8(encoder, &atom->u.as_bytes);
  case PNE_SYM32: return pn_encoder_writev32(encoder, &atom->u.as_bytes);
  case PNE_ARRAY32:
    node->start = encoder->position;
    node->small = false;
    // we'll backfill the size on exit
    if (pn_encoder_remaining(encoder) < 4) return PN_OVERFLOW;
    encoder->position += 4;

    err = pn_encoder_writef32(encoder, node->described ? node->children - 1 : node->children);
    if (err) return err;

    if (node->described) {
      err = pn_encoder_writef8(encoder, 0);
      if (err) return err;
    }
    return 0;
  case PNE_LIST32:
  case PNE_MAP32:
    node->start = encoder->position;
    node->small = false;
    // we'll backfill the size later
    if (pn_encoder_remaining(encoder) < 4) return PN_OVERFLOW;
    encoder->position += 4;
    return pn_encoder_writef32(encoder, node->children);
  default:
    return pn_error_format(data->error, PN_ERR, "unrecognized encoding: %u", code);
  }
}