static int event_on_accept (struct event_data *self, struct kevent *event) {
  struct sockaddr client;
  socklen_t client_len = sizeof(client);

  int client_fd = accept(server_fd, &client, &client_len);
  int flags;
  int err;

  if (client_fd < 0) {
    if (errno == EWOULDBLOCK || errno == EAGAIN) return 0;
    on_error("Accept failed (should this be fatal?): %s\n", strerror(errno));
  }

  flags = fcntl(client_fd, F_GETFL, 0);
  if (flags < 0) on_error("Could not get client socket flags: %s\n", strerror(errno));

  err = fcntl(client_fd, F_SETFL, flags | O_NONBLOCK);
  if (err < 0) on_error("Could not set client socket to be non blocking: %s\n", strerror(errno));

  struct event_data *client_data = (struct event_data *) malloc(sizeof(struct event_data));
  client_data->on_read = event_on_read;
  client_data->on_write = event_on_write;

  event_change(client_fd, EVFILT_READ, EV_ADD | EV_ENABLE, client_data);
  event_change(client_fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, client_data);

  return 1;
}
static int event_on_read (struct event_data *self, struct kevent *event) {
  if (self->buffer_read == BUFFER_SIZE) {
    event_change(event->ident, EVFILT_READ, EV_DISABLE, self);
    return 0;
  }

  int n = read(event->ident, self->buffer + self->buffer_read, BUFFER_SIZE - self->buffer_read);

  if (n < 0) {
    if (errno == EWOULDBLOCK || errno == EAGAIN) return 0;
    on_error("Read failed (should this be fatal?): %s\n", strerror(errno));
  }

  if (n == 0) {
    free(self);
    close(event->ident);
    return 0;
  }

  if (self->buffer_read == 0) {
    event_change(event->ident, EVFILT_WRITE, EV_ENABLE, self);
  }

  self->buffer_read += n;
  return event_flush_write(self, event);
}
Esempio n. 3
0
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
{
  jvmtiEventCallbacks *evCbs;
  jvmtiCapabilities caps;
  jvmtiEnv *jvmti;
  jint rc;
  jint jvmtiVer;

  agent_options = options ? strdup(options) : "";
  evCbs = get_jvmti_callbacks();

  memset(evCbs, 0, sizeof(*evCbs));
  memset(&caps, 0, sizeof(caps));

  evCbs->VMInit = cbVMInit;
  evCbs->VMDeath = cbVMDeath;
  caps.can_generate_breakpoint_events = 1;
  caps.can_generate_method_entry_events = 1;
  caps.can_generate_method_exit_events = 1;
  caps.can_generate_exception_events = 1;
  caps.can_tag_objects = 1;
  caps.can_get_source_file_name = 1;
  caps.can_get_line_numbers = 1;
  caps.can_access_local_variables = 1;
  caps.can_generate_single_step_events = 1; /* Used for line-oriented stepping */
/*   caps.can_generate_frame_pop_events = 1; */
  caps.can_force_early_return = 1;

  rc = (*jvm)->GetEnv(jvm, (void **)&jvmti, JVMTI_VERSION_1_0);
  if(rc < 0)
  {
	fprintf(stderr, "Failed to get JVMTI env\n");
	return JNI_ERR;
  }

  Gagent.jvm = jvm;
  Gagent.jvmti = jvmti;
  Gagent.jerr = (*Gagent.jvmti)->GetVersionNumber(Gagent.jvmti, &jvmtiVer);
  check_jvmti_error(Gagent.jvmti, Gagent.jerr);
  printf("JVMTI version %d.%d.%d\n",
		 (jvmtiVer & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR,
		 (jvmtiVer & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR,
		 (jvmtiVer & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO);
  Gagent.jerr = (*Gagent.jvmti)->AddCapabilities(Gagent.jvmti, &caps);
  check_jvmti_error(Gagent.jvmti, Gagent.jerr);
  Gagent.jerr = (*Gagent.jvmti)->SetEventCallbacks(Gagent.jvmti,
												   evCbs, sizeof(jvmtiEventCallbacks));
  check_jvmti_error(Gagent.jvmti, Gagent.jerr);
  /* Check that any calls to SetEventNotificationMode are valid in the
     OnLoad phase before calling here. */
  Gagent.jerr = event_change(Gagent.jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL);
  check_jvmti_error(Gagent.jvmti, Gagent.jerr);
  Gagent.jerr = event_change(Gagent.jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL);
  check_jvmti_error(Gagent.jvmti, Gagent.jerr);

  return JNI_OK;
}
static int event_on_write (struct event_data *self, struct kevent *event) {
  if (self->buffer_read == self->buffer_write) {
    event_change(event->ident, EVFILT_WRITE, EV_DISABLE, self);
    return 0;
  }

  return event_flush_write(self, event);
}
int main (int argc, char *argv[]) {
  if (argc < 2) {
    printf("Usage: %s [socket-path]\n", argv[0]);
    exit(1);
  }

  struct event_data server = {
    .on_read = event_on_accept,
    .on_write = NULL
  };

  event_server_listen(argv[1]);
  event_change(server_fd, EVFILT_READ, EV_ADD | EV_ENABLE, &server);
  event_loop();

  return 0;
}