Exemplo n.º 1
0
int lp_check_file(lua_State *ls)
{
	FILE *f;
	char *aux;
	unsigned long int size=0L;
	unsigned long int size2=0L;

	aux=(char *)malloc(sizeof(char)*512);
	if (aux==NULL) {
		ph_log_memory_error((char *)"luaphant.c",(char *)"lp_check_file",(char *)"aux",sizeof(char)*512);
	}
	memset(aux,0,sizeof(char)*512);
	strcpy(aux,lua_tostring(ls,1));
	f=fopen(aux,"rb");
	if (f==NULL) {
		ph_log(_("Fatal error: Can't find the file %s."),aux);
		exit(-1);
	}

	fseek(f,0,SEEK_END);
	size=ftell(f);
	fseek(f,0,SEEK_SET);

	size2=(unsigned long int)lua_tonumber(ls,2);

	if (size!=size2) {
		ph_log(_("Fatal error: Size doesn't match."));
		exit(-1);
	}

	fclose(f);
	free(aux);
	return 0;
}
Exemplo n.º 2
0
char * ph_get_path(CFG *cfg, char *path, char *buffer)
{
	FILE *f,*f1;
	memset(path,0,sizeof(char)*MAXPATHSIZE);
	strcpy(path,buffer);
	f=fopen(path,"r");
	if (f==NULL) {
		/* Ok, no está en la ruta normal, mirar a ver si está en el directorio actual */
		/* En sistemas Unix cuya shell ponga el valor de la variable PWD */
		/* TODO Mirar a ver si hay alguna manera portable */
		#ifndef WIN32
		#ifndef DOS
		#ifndef CUSTOM_PATH
		memset(path,0,sizeof(char)*MAXPATHSIZE);
		strcpy(path,getenv("PWD"));
		path[strlen(path)]='/';
		strcat(path,buffer);
		f=fopen(path,"r");
		if (f==NULL) {
			ph_log(_("- Error: According to function ph_get_path the file %s doesn't exist.\n"),path);
			return NULL;
		}
		else {
			fclose(f);
			return path;
		}
		#endif
		#endif
		#endif

		memset(path,0,sizeof(char)*MAXPATHSIZE);
		#ifdef CUSTOM_PATH
		strcat(path,"/usr/share/phantomaspc/");
		strcat(path,buffer);
		#else
		strcpy(path,buffer);
		#endif
		f1=fopen(path,"rb");
		if (f1==NULL) {
			ph_log(_("- Error: According to function ph_get_path the file %s doesn't exist.\n"),path);
			return NULL;
		}
		fclose(f1);
		return path;
	}
	fclose(f);
	return path;
}
Exemplo n.º 3
0
static void read_remote(ph_sock_t *sock, ph_iomask_t why, void *data)
{
  ph_buf_t *buf;

  ph_unused_parameter(data);

  if (why & (PH_IOMASK_TIME|PH_IOMASK_ERR)) {
    ph_log(PH_LOG_ERR, "disconnecting `P{sockaddr:%p}",
        (void*)&sock->peername);
    ph_sock_shutdown(sock, PH_SOCK_SHUT_RDWR);
    ph_sock_free(sock);
    remote_sock = NULL;
    ph_sched_stop();
    return;
  }

  while (1) {
    buf = ph_sock_read_line(sock);
    if (!buf) {
      // Not available yet, we'll try again later
      return;
    }

    ph_ignore_result(write(STDOUT_FILENO, ph_buf_mem(buf), ph_buf_len(buf)));
    ph_buf_delref(buf);
  }
}
Exemplo n.º 4
0
static void read_stdin(ph_job_t *job, ph_iomask_t why, void *data)
{
  char buf[128];
  int x, i;

  ph_unused_parameter(why);
  ph_unused_parameter(data);

  x = read(job->fd, buf, sizeof(buf));
  if (x <= 0) {
    if (x == -1) {
      ph_log(PH_LOG_ERR, "read(stdin): `Pe%d", errno);
    }
    ph_sched_stop();
    return;
  }

  // Writing to the other job is safe here because we have the
  // same affinity: we know that it is not executing and mutating
  // its state
  for (i = 0; i < x; i++) {
    if (buf[i] == '\n') {
      ph_stm_write(remote_sock->stream, "\r\n", 2, NULL);
    } else {
      ph_stm_write(remote_sock->stream, buf + i, 1, NULL);
    }
  }

  // Force the sock to wakeup and send the buffer.
  // FIXME: Need something nicer than this hack
  ph_sock_enable(remote_sock, false);
  ph_sock_enable(remote_sock, true);

  ph_job_set_nbio_timeout_in(job, PH_IOMASK_READ, timeout);
}
Exemplo n.º 5
0
static void connected(ph_sock_t *sock, int overall_status,
    int errcode, const ph_sockaddr_t *addr,
    struct timeval *elapsed, void *arg)
{
  SSL_CTX *ctx;
  SSL *ssl;

  ph_unused_parameter(arg);
  ph_unused_parameter(elapsed);

  switch (overall_status) {
    case PH_SOCK_CONNECT_GAI_ERR:
      ph_log(PH_LOG_ERR, "resolve %s:%d failed %s",
          addrstring, portno, gai_strerror(errcode));
      ph_sched_stop();
      return;

    case PH_SOCK_CONNECT_ERRNO:
      ph_log(PH_LOG_ERR, "connect %s:%d (`P{sockaddr:%p}) failed: `Pe%d",
          addrstring, portno, (void*)addr, errcode);
      ph_sched_stop();
      return;
  }

  sock->callback = read_remote;
  remote_sock = sock;

  // Now set up stdin to feed into this new sock
  ph_job_init(&stdin_job);
  stdin_job.fd = STDIN_FILENO;
  stdin_job.callback = read_stdin;
  // Ensure that we have the same affinity as the other job
  stdin_job.emitter_affinity = sock->job.emitter_affinity;
  ph_socket_set_nonblock(STDIN_FILENO, true);
  ph_job_set_nbio_timeout_in(&stdin_job, PH_IOMASK_READ, timeout);

  ctx = SSL_CTX_new(SSLv23_client_method());
  SSL_CTX_set_cipher_list(ctx, "ALL");
  SSL_CTX_set_options(ctx, SSL_OP_ALL);
  SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
  ssl = SSL_new(ctx);
  ph_sock_openssl_enable(sock, ssl, true, done_handshake);

  ph_sock_enable(sock, true);
}
Exemplo n.º 6
0
lua_State * lp_init_lua(void)
{
	lua_State *ls;

	ph_log(_("- Initiating Lua: "));
	ls=luaL_newstate();

	if (ls==NULL) {
		ph_log(_("Fatal error: Can't init Lua.\n"));
		exit(13);
	}
	else {
		ph_log(_("Ok.\n"));
	}
	ls=lp_register_luaphant_functions(ls);
	luaL_openlibs(ls);
	return ls;
}
Exemplo n.º 7
0
void ph_panic(const char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  ph_logv(PH_LOG_PANIC, fmt, ap);
  va_end(ap);

  ph_log(PH_LOG_PANIC, "Fatal error detected at:");
  ph_log_stacktrace(PH_LOG_PANIC);
  abort();
}
Exemplo n.º 8
0
// Called each time the session wakes up.
// The `why` parameter indicates why we were woken up
static void echo_processor(ph_sock_t *sock, ph_iomask_t why, void *arg)
{
  struct echo_state *state = arg;
  ph_buf_t *buf;

  // If the socket encountered an error, or if the timeout was reached
  // (there's a default timeout, even if we didn't override it), then
  // we tear down the session
  if (why & (PH_IOMASK_ERR|PH_IOMASK_TIME)) {
    ph_log(PH_LOG_ERR, "disconnecting `P{sockaddr:%p}", (void*)&sock->peername);
    ph_sock_shutdown(sock, PH_SOCK_SHUT_RDWR);
    ph_mem_free(mt_state, state);
    ph_sock_free(sock);
    return;
  }

  // We loop because echo_processor is only triggered by newly arriving
  // data or events from the kernel.  If we have data buffered and only
  // partially consume it, we won't get woken up until the next data
  // arrives, if ever.
  while (1) {
    // Try to read a line of text.
    // This returns a slice over the underlying buffer (if the line was
    // smaller than a buffer) or a freshly made contiguous buffer (if the
    // line was larger than our buffer segment size).  Either way, we
    // own a reference to the returned buffer and should treat it as
    // a read-only slice.
    buf = ph_sock_read_line(sock);
    if (!buf) {
      // Not available yet, we'll try again later
      return;
    }

    // We got a line; update our state
    state->num_lines++;

    // Send our response.  The data is buffered and automatically sent
    // to the client as it becomes writable, so we don't need to handle
    // partial writes or EAGAIN here.

    // If this was a "real" server, we would still check the return value
    // from the writes and proceed to tear down the session if things failed.

    // Note that buf includes the trailing CRLF, so our response
    // will implicitly end with CRLF too.
    ph_stm_printf(sock->stream, "You said [%d]: ", state->num_lines);
    ph_stm_write(sock->stream, ph_buf_mem(buf), ph_buf_len(buf), NULL);

    // We're done with buf, so we must release it
    ph_buf_delref(buf);
  }
}
Exemplo n.º 9
0
// Called each time the listener has accepted a client connection
static void acceptor(ph_listener_t *lstn, ph_sock_t *sock)
{
  ph_unused_parameter(lstn);

  // Allocate an echo_state instance and stash it.
  // This is set to be zero'd on creation and will show up as the
  // `arg` parameter in `echo_processor`
  sock->job.data = ph_mem_alloc(mt_state);

  // Tell it how to dispatch
  sock->callback = echo_processor;

  ph_log(PH_LOG_ERR, "accepted `P{sockaddr:%p}", (void*)&sock->peername);

  ph_sock_enable(sock, true);
}
Exemplo n.º 10
0
void ph_log_stacktrace(uint8_t level)
{
#if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS)
  void *array[24];
  size_t size;
  char **strings;
  size_t i;

  size = backtrace(array, sizeof(array)/sizeof(array[0]));
  strings = backtrace_symbols(array, size);

  for (i = 0; i < size; i++) {
    ph_log(level, "%s", strings[i]);
  }

  free(strings);
#endif
}
Exemplo n.º 11
0
/* {
 *   "base": 0, // base core number; is added to "selector"
 *   "selector": "tid", // use tid
 *   "selector": "wid", // use thr->is_worker id
 *   "selector": [1,2,3],  // use 1+base, 2+base, 3+base
 *   "selector": 1, // use 1+base
 *   "selector": "none" // don't specify affinity
 * }
 */
bool ph_thread_set_affinity_policy(ph_thread_t *me, ph_variant_t *policy)
{
  ph_cpu_set_t set;
  uint32_t cores = ph_num_cores();

  CPU_ZERO(&set);
  if (!policy) {
    ph_cpu_set(me->tid % cores, &set);
  } else {
    int base = 0;
    ph_var_err_t err;
    ph_variant_t *sel = NULL;

    ph_var_unpack(policy, &err, 0, "{si, so}", "base", &base, "selector", &sel);

    if (sel && ph_var_is_array(sel)) {
      uint32_t i;

      for (i = 0; i < ph_var_array_size(sel); i++) {
        int cpu = ph_var_int_val(ph_var_array_get(sel, i));
        ph_cpu_set((base + cpu) % cores, &set);
      }
    } else if (sel && ph_var_is_string(sel)) {
      ph_string_t *s = ph_var_string_val(sel);
      if (ph_string_equal_cstr(s, "tid")) {
        ph_cpu_set((base + me->tid) % cores, &set);
      } else if (ph_string_equal_cstr(s, "wid")) {
        ph_cpu_set((base + me->is_worker - 1) % cores, &set);
      } else if (ph_string_equal_cstr(s, "none")) {
        return true;
      } else {
        ph_log(PH_LOG_ERR, "Unknown thread affinity selector `Ps%p",
            (void*)s);
      }
    } else if (sel && ph_var_is_int(sel)) {
      ph_cpu_set((base + ph_var_int_val(sel)) % cores, &set);
    } else {
      ph_cpu_set((base + me->tid) % cores, &set);
    }
  }

  return apply_affinity(&set, me);
}
Exemplo n.º 12
0
int main(int argc, char **argv)
{
  int c;
  uint16_t portno = 8080;
  char *addrstring = NULL;
  ph_sockaddr_t addr;
  ph_listener_t *lstn;
  bool use_v4 = false;

  // Must be called prior to calling any other phenom functions
  ph_library_init();

  while ((c = getopt(argc, argv, "p:l:4")) != -1) {
    switch (c) {
      case '4':
        use_v4 = true;
        break;
      case 'l':
        addrstring = optarg;
        break;
      case 'p':
        portno = atoi(optarg);
        break;
      default:
        ph_fdprintf(STDERR_FILENO,
            "Invalid parameters\n"
            " -4          - interpret address as an IPv4 address\n"
            " -l ADDRESS  - which address to listen on\n"
            " -p PORTNO   - which port to listen on\n"
        );
        exit(EX_USAGE);
    }
  }

  // Set up the address that we're going to listen on
  if ((use_v4 && ph_sockaddr_set_v4(&addr, addrstring, portno) != PH_OK) ||
      (!use_v4 && ph_sockaddr_set_v6(&addr, addrstring, portno) != PH_OK)) {
    ph_fdprintf(STDERR_FILENO,
        "Invalid address [%s]:%d",
        addrstring ? addrstring : "*",
        portno
    );
    exit(EX_USAGE);
  }

  // Register our memtype
  mt_state = ph_memtype_register(&mt_state_def);

  // Optional config file for tuning internals
  ph_config_load_config_file("/path/to/my/config.json");

  // Enable the non-blocking IO manager
  ph_nbio_init(0);

  ph_log(PH_LOG_ERR, "will listen on `P{sockaddr:%p}", (void*)&addr);

  // This enables a very simple request/response console
  // that allows you to run diagnostic commands:
  // `echo memory | nc -UC /tmp/phenom-debug-console`
  // (on BSD systems, use `nc -Uc`!)
  // The code behind this is in
  // https://github.com/facebook/libphenom/blob/master/corelib/debug_console.c
  ph_debug_console_start("/tmp/phenom-debug-console");

  lstn = ph_listener_new("echo-server", acceptor);
  ph_listener_bind(lstn, &addr);
  ph_listener_enable(lstn, true);

  // Run
  ph_sched_run();

  return 0;
}
Exemplo n.º 13
0
ph_result_t ph_nbio_emitter_apply_io_mask(
    struct ph_nbio_emitter *emitter, ph_job_t *job, ph_iomask_t mask)
{
    struct epoll_event evt;
    int res;
    int want_mask;

    if (job->fd == -1) {
        return PH_OK;
    }

    switch (mask & (PH_IOMASK_READ|PH_IOMASK_WRITE)) {
    case PH_IOMASK_READ|PH_IOMASK_WRITE:
        want_mask = EPOLLIN|EPOLLOUT|DEFAULT_POLL_MASK;
        break;
    case PH_IOMASK_READ:
        want_mask = EPOLLIN|DEFAULT_POLL_MASK;
        break;
    case PH_IOMASK_WRITE:
        want_mask = EPOLLOUT|DEFAULT_POLL_MASK;
        break;
    case 0:
    default:
        want_mask = 0;
        break;
    }

    if (want_mask == 0) {
        job->mask = 0;
        job->kmask = 0;
        res = epoll_ctl(emitter->io_fd, EPOLL_CTL_DEL, job->fd, &evt);
        if (res < 0 && errno == ENOENT) {
            res = 0;
        }
    } else {
        int op = job->kmask ? EPOLL_CTL_MOD : EPOLL_CTL_ADD;
        evt.events = want_mask;
        evt.data.ptr = job;

        // Set the masks on the job before we epoll_ctl as it
        // may arrive at another thread *before* epoll_ctl returns
        job->kmask = want_mask;
        job->mask = mask;
        res = epoll_ctl(emitter->io_fd, op, job->fd, &evt);
        if (res == -1 && errno == EEXIST && op == EPOLL_CTL_ADD) {
            // This can happen when we're transitioning between distinct job
            // pointers, for instance, when we're moving from an async connect
            // to setting up the sock job
            res = epoll_ctl(emitter->io_fd, EPOLL_CTL_MOD, job->fd, &evt);
        } else if (res == -1 && errno == ENOENT && op == EPOLL_CTL_MOD) {
            res = epoll_ctl(emitter->io_fd, EPOLL_CTL_ADD, job->fd, &evt);
        }

        if (res == -1 && errno == EEXIST) {
            res = 0;
        }
    }

    if (res == -1) {
        ph_log(PH_LOG_ERR,
               "fd=%d (callback=%p) epoll_ctl: setting mask to %02x -> %d `Pe%d",
               job->fd, (void*)(uintptr_t)job->callback, mask, errno, errno);
        ph_log_stacktrace(PH_LOG_ERR);
        return PH_ERR;
    }
    return PH_OK;
}
Exemplo n.º 14
0
void ph_nbio_emitter_run(struct ph_nbio_emitter *emitter, ph_thread_t *thread)
{
    struct epoll_event *event;
    int n, i;
    int max_chunk, max_sleep;

    max_chunk = ph_config_query_int("$.nbio.max_per_wakeup", 1024);
    max_sleep = ph_config_query_int("$.nbio.max_sleep", 5000);
    event = malloc(max_chunk * sizeof(struct epoll_event));

    while (ck_pr_load_int(&_ph_run_loop)) {
        n = epoll_wait(emitter->io_fd, event, max_chunk, max_sleep);
        thread->refresh_time = true;

        if (n < 0) {
            if (errno != EINTR) {
                ph_log(PH_LOG_ERR, "epoll_wait: `Pe%d", errno);
            }
            ph_job_collector_emitter_call(emitter);
            ph_thread_epoch_poll();
            continue;
        }

        if (n == 0) {
            continue;
        }

        ph_thread_epoch_begin();
        for (i = 0; i < n; i++) {
            ph_iomask_t mask = 0;
            ph_job_t *job = event[i].data.ptr;

            if (job->mask == 0) {
                // Ignore: disabled for now
                continue;
            }

            switch (event[i].events & (EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
            case EPOLLIN:
                mask = PH_IOMASK_READ;
                break;
            case EPOLLOUT:
                mask = PH_IOMASK_WRITE;
                break;
            case EPOLLIN|EPOLLOUT:
                mask = PH_IOMASK_READ|PH_IOMASK_WRITE;
                break;
            default:
                mask = PH_IOMASK_ERR;
            }
            // We can't just clear kmask completely because ONESHOT retains
            // the existence of the item; we need to know it is there so that
            // we can MOD it instead of ADD it later.
            job->kmask = DEFAULT_POLL_MASK;
            ph_nbio_emitter_dispatch_immediate(emitter, job, mask);
            if (ph_job_have_deferred_items(thread)) {
                ph_job_pool_apply_deferred_items(thread);
            }
        }
        ph_thread_epoch_end();
        ph_job_collector_emitter_call(emitter);
        ph_thread_epoch_poll();
    }

    free(event);
}
Exemplo n.º 15
0
static void done_handshake(ph_sock_t *sock, int res)
{
  ph_unused_parameter(sock);
  ph_log(PH_LOG_ERR, "handshake completed with res=%d", res);
}