Ejemplo n.º 1
0
static void ns_write_to_socket(struct ns_connection *conn) {
  struct iobuf *io = &conn->send_iobuf;
  int n = 0;

#ifdef NS_ENABLE_SSL
  if (conn->ssl != NULL) {
    n = SSL_write(conn->ssl, io->buf, io->len);
    if (n <= 0) {
      int ssl_err = ns_ssl_err(conn, n);
      if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
        return; /* Call us again */
      } else {
        conn->flags |= NSF_CLOSE_IMMEDIATELY;
      }
    }
  } else
#endif
  { n = (int) send(conn->sock, io->buf, io->len, 0); }

  DBG(("%p %lu -> %d bytes", conn, conn->flags, n));

  ns_call(conn, NS_SEND, &n);
  if (ns_is_error(n)) {
    conn->flags |= NSF_CLOSE_IMMEDIATELY;
  } else if (n > 0) {
    iobuf_remove(io, n);
  }
}
Ejemplo n.º 2
0
static void ns_read_from_socket(struct ns_connection *conn) {
  char buf[NS_READ_BUFFER_SIZE];
  int n = 0;

  if (conn->flags & NSF_CONNECTING) {
    int ok = 1, ret;
    (void) ret;

    socklen_t len = sizeof(ok);

    ret = getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *) &ok, &len);
#ifdef NS_ENABLE_SSL
    if (ret == 0 && ok == 0 && conn->ssl != NULL) {
      ns_ssl_begin(conn);
    }
#endif
    DBG(("%p connect ok=%d", conn, ok));
    if (ok != 0) {
      conn->flags |= NSF_CLOSE_IMMEDIATELY;
    } else {
      conn->flags &= ~NSF_CONNECTING;
    }
    ns_call(conn, NS_CONNECT, &ok);
    return;
  }

#ifdef NS_ENABLE_SSL
  if (conn->ssl != NULL) {
    if (conn->flags & NSF_SSL_HANDSHAKE_DONE) {
      /* SSL library may have more bytes ready to read then we ask to read.
       * Therefore, read in a loop until we read everything. Without the loop,
       * we skip to the next select() cycle which can just timeout. */
      while ((n = SSL_read(conn->ssl, buf, sizeof(buf))) > 0) {
        DBG(("%p %d bytes <- %d (SSL)", conn, n, conn->sock));
        mbuf_append(&conn->recv_mbuf, buf, n);
        ns_call(conn, NS_RECV, &n);
      }
      ns_ssl_err(conn, n);
    } else {
      ns_ssl_begin(conn);
      return;
    }
  } else
#endif
  {
    while ((n = (int) NS_RECV_FUNC(
                conn->sock, buf, recv_avail_size(conn, sizeof(buf)), 0)) > 0) {
      DBG(("%p %d bytes (PLAIN) <- %d", conn, n, conn->sock));
      mbuf_append(&conn->recv_mbuf, buf, n);
      ns_call(conn, NS_RECV, &n);
    }
  }

  if (ns_is_error(n)) {
    conn->flags |= NSF_CLOSE_IMMEDIATELY;
  }
}
Ejemplo n.º 3
0
static void ns_write_to_socket(struct ns_connection *conn) {
  struct mbuf *io = &conn->send_mbuf;
  int n = 0;

  assert(io->len > 0);

#ifdef NS_ENABLE_SSL
  if (conn->ssl != NULL) {
    if (conn->flags & NSF_SSL_HANDSHAKE_DONE) {
      n = SSL_write(conn->ssl, io->buf, io->len);
      if (n <= 0) {
        int ssl_err = ns_ssl_err(conn, n);
        if (ssl_err == SSL_ERROR_WANT_READ || ssl_err == SSL_ERROR_WANT_WRITE) {
          return; /* Call us again */
        } else {
          conn->flags |= NSF_CLOSE_IMMEDIATELY;
        }
      } else {
        /* Successful SSL operation, clear off SSL wait flags */
        conn->flags &= ~(NSF_WANT_READ | NSF_WANT_WRITE);
      }
    } else {
      ns_ssl_begin(conn);
      return;
    }
  } else
#endif
  {
    n = (int) NS_SEND_FUNC(conn->sock, io->buf, io->len, 0);
  }

  DBG(("%p %d bytes -> %d", conn, n, conn->sock));

  if (ns_is_error(n)) {
    conn->flags |= NSF_CLOSE_IMMEDIATELY;
  } else if (n > 0) {
#ifndef NS_DISABLE_FILESYSTEM
    /* LCOV_EXCL_START */
    if (conn->mgr->hexdump_file != NULL) {
      ns_hexdump_connection(conn, conn->mgr->hexdump_file, n, NS_SEND);
    }
/* LCOV_EXCL_STOP */
#endif
    mbuf_remove(io, n);
  }
  ns_call(conn, NS_SEND, &n);
}
Ejemplo n.º 4
0
/*
 * Schedules an async connect for a resolved address and proto.
 * Called from two places: `ns_connect_opt()` and from async resolver.
 * When called from the async resolver, it must trigger `NS_CONNECT` event
 * with a failure flag to indicate connection failure.
 */
NS_INTERNAL struct ns_connection *ns_finish_connect(struct ns_connection *nc,
                                                    int proto,
                                                    union socket_address *sa,
                                                    struct ns_add_sock_opts o) {
  sock_t sock = INVALID_SOCKET;
  int rc;

  DBG(("%p %s://%s:%hu", nc, proto == SOCK_DGRAM ? "udp" : "tcp",
       inet_ntoa(nc->sa.sin.sin_addr), ntohs(nc->sa.sin.sin_port)));

  if ((sock = socket(AF_INET, proto, 0)) == INVALID_SOCKET) {
    int failure = errno;
    NS_SET_PTRPTR(o.error_string, "cannot create socket");
    if (nc->flags & NSF_CONNECTING) {
      ns_call(nc, NS_CONNECT, &failure);
    }
    ns_destroy_conn(nc);
    return NULL;
  }

  ns_set_non_blocking_mode(sock);
  rc = (proto == SOCK_DGRAM) ? 0 : connect(sock, &sa->sa, sizeof(sa->sin));

  if (rc != 0 && ns_is_error(rc)) {
    NS_SET_PTRPTR(o.error_string, "cannot connect to socket");
    if (nc->flags & NSF_CONNECTING) {
      ns_call(nc, NS_CONNECT, &rc);
    }
    ns_destroy_conn(nc);
    close(sock);
    return NULL;
  }

  /* Fire NS_CONNECT on next poll. */
  nc->flags |= NSF_CONNECTING;

  /* No ns_destroy_conn() call after this! */
  ns_set_sock(nc, sock);
  return nc;
}
Ejemplo n.º 5
0
NsError ns_model_read_swc
	(
	NsModel       *model,
	NsSwcHeader   *swc_header,
	const nschar  *file_name,
	nsulong        flags,
	nslong        *line_num
	)
	{
	NsError error;

	ns_assert( NULL != model );
	ns_assert( NULL != swc_header );
	ns_assert( NULL != file_name );

	ns_log_entry(
		NS_LOG_ENTRY_FUNCTION,
		NS_FUNCTION
		"( model=" NS_FMT_STRING_DOUBLE_QUOTED
		", swc_header=" NS_FMT_POINTER
		", file_name=" NS_FMT_STRING_DOUBLE_QUOTED
		", flags=" NS_FMT_ULONG
		", line_num=" NS_FMT_POINTER
		" )",
		ns_model_get_name( model ),
		swc_header,
		file_name,
		flags,
		line_num
		);

	error = ( flags & NS_SWC_MULTIPLE_FILES ) ?
					_ns_swc_read_multi_file( model, swc_header, file_name, flags, line_num ) :
					_ns_swc_read_single_file( model, swc_header, file_name, flags, line_num );

	if( ! ns_is_error( error ) )
		ns_model_function_edges_from_vertices( model );

	return error;
	}
Ejemplo n.º 6
0
/*
 * Connect to a remote host.
 *
 * If successful, `NS_CONNECT` event will be delivered
 * to the new connection. `addr` format is the same as for the `ns_bind()` call,
 * just an IP address becomes mandatory: `[PROTO://]HOST:PORT`.
 *
 * `PROTO` could be `tcp://` or `udp://`. If `HOST` is not an IP
 * address, Fossa will resolve it - beware that standard blocking resolver
 * will be used. It is a good practice to pre-resolve hosts beforehands and
 * use only IP addresses to avoid blockin an IO thread.
 *
 * See the `ns_connect_opts` structure for a description of the optional
 * parameters.
 *
 * Returns a new outbound connection, or `NULL` on error.
*/
struct ns_connection *ns_connect_opt(struct ns_mgr *mgr, const char *address,
                                     ns_event_handler_t callback,
                                     struct ns_connect_opts opts) {
  sock_t sock = INVALID_SOCKET;
  struct ns_connection *nc = NULL;
  union socket_address sa;
  int rc, proto;
  struct ns_add_sock_opts add_sock_opts;

  if (ns_parse_address(address, &sa, &proto) == 0) {
    errno = 0;
    ns_set_error_string(opts.error_string, "cannot parse address");
    return NULL;
  }
  if ((sock = socket(AF_INET, proto, 0)) == INVALID_SOCKET) {
    ns_set_error_string(opts.error_string, "cannot create socket");
    return NULL;
  }

  ns_set_non_blocking_mode(sock);
  rc = (proto == SOCK_DGRAM) ? 0 : connect(sock, &sa.sa, sizeof(sa.sin));

  NS_COPY_COMMON_CONNECTION_OPTIONS(&add_sock_opts, &opts);

  if (rc != 0 && ns_is_error(rc)) {
    ns_set_error_string(opts.error_string, "cannot connect to socket");
    closesocket(sock);
    return NULL;
  } else if ((nc = ns_add_sock_opt(mgr, sock, callback, add_sock_opts)) == NULL) {
    /* opts.error_string set by ns_add_sock_opt */
    closesocket(sock);
    return NULL;
  }

  nc->sa = sa;   /* Important, cause UDP conns will use sendto() */
  nc->flags |= (proto == SOCK_DGRAM) ? NSF_UDP : NSF_CONNECTING;

  return nc;
}
Ejemplo n.º 7
0
static void ns_read_from_socket(struct ns_connection *conn) {
  char buf[NS_READ_BUFFER_SIZE];
  int n = 0;

  if (conn->flags & NSF_CONNECTING) {
    int ok = 1, ret;
    socklen_t len = sizeof(ok);

    ret = getsockopt(conn->sock, SOL_SOCKET, SO_ERROR, (char *) &ok, &len);
#ifdef NS_ENABLE_SSL
    if (ret == 0 && ok == 0 && conn->ssl != NULL) {
      int res = SSL_connect(conn->ssl);
      int ssl_err = ns_ssl_err(conn, res);
      if (res == 1) {
        conn->flags |= NSF_SSL_HANDSHAKE_DONE;
      } else if (ssl_err == SSL_ERROR_WANT_READ ||
                 ssl_err == SSL_ERROR_WANT_WRITE) {
        return; /* Call us again */
      } else {
        ok = 1;
      }
    }
#endif
    conn->flags &= ~NSF_CONNECTING;
    DBG(("%p ok=%d", conn, ok));
    if (ok != 0) {
      conn->flags |= NSF_CLOSE_IMMEDIATELY;
    }
    ns_call(conn, NS_CONNECT, &ok);
    return;
  }

#ifdef NS_ENABLE_SSL
  if (conn->ssl != NULL) {
    if (conn->flags & NSF_SSL_HANDSHAKE_DONE) {
      /* SSL library may have more bytes ready to read then we ask to read.
       * Therefore, read in a loop until we read everything. Without the loop,
       * we skip to the next select() cycle which can just timeout. */
      while ((n = SSL_read(conn->ssl, buf, sizeof(buf))) > 0) {
        DBG(("%p %lu <- %d bytes (SSL)", conn, conn->flags, n));
        iobuf_append(&conn->recv_iobuf, buf, n);
        ns_call(conn, NS_RECV, &n);
      }
      ns_ssl_err(conn, n);
    } else {
      int res = SSL_accept(conn->ssl);
      int ssl_err = ns_ssl_err(conn, res);
      if (res == 1) {
        conn->flags |= NSF_SSL_HANDSHAKE_DONE;
      } else if (ssl_err == SSL_ERROR_WANT_READ ||
                 ssl_err == SSL_ERROR_WANT_WRITE) {
        return; /* Call us again */
      } else {
        conn->flags |= NSF_CLOSE_IMMEDIATELY;
      }
      return;
    }
  } else
#endif
  {
    while ((n = (int) recv(conn->sock, buf, sizeof(buf), 0)) > 0) {
      DBG(("%p %lu <- %d bytes (PLAIN)", conn, conn->flags, n));
      iobuf_append(&conn->recv_iobuf, buf, n);
      ns_call(conn, NS_RECV, &n);
    }
  }

  if (ns_is_error(n)) {
    conn->flags |= NSF_CLOSE_IMMEDIATELY;
  }
}