struct tlv_packet *webcam_get_frame(struct tlv_handler_ctx *ctx) { fd_set fds; struct timeval tv; int r; FD_ZERO(&fds); FD_SET(fd, &fds); /* Timeout. */ tv.tv_sec = 1; tv.tv_usec = 0; r = select(fd + 1, &fds, NULL, NULL, &tv); if (r == -1) { return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); } struct v4l2_buffer buf; CLEAR(buf); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; if (xioctl(fd, VIDIOC_DQBUF, &buf) == -1 || buf.index >= n_buffers) { return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); } struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); p = tlv_packet_add_raw(p, TLV_TYPE_WEBCAM_IMAGE, buffers[buf.index].start, buf.length); if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); } return p; }
static struct tlv_packet *core_set_session_guid(struct tlv_handler_ctx *ctx) { size_t guid_len = 0; struct mettle *m = ctx->arg; struct tlv_dispatcher *td = mettle_get_tlv_dispatcher(m); char *guid = tlv_packet_get_raw(ctx->req, TLV_TYPE_SESSION_GUID, &guid_len); if (!guid || guid_len != SESSION_GUID_LEN) return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); tlv_dispatcher_set_session_guid(td, guid); return tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); }
static struct tlv_packet *core_uuid(struct tlv_handler_ctx *ctx) { size_t uuid_len; struct mettle *m = ctx->arg; struct tlv_dispatcher *td = mettle_get_tlv_dispatcher(m); const char *uuid = tlv_dispatcher_get_uuid(td, &uuid_len); if (uuid && uuid_len) { struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); return tlv_packet_add_raw(p, TLV_TYPE_UUID, uuid, uuid_len); } return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); }
struct tlv_packet *sys_config_getenv(struct tlv_handler_ctx *ctx) { struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); struct tlv_iterator i = { .packet = ctx->req, .value_type = TLV_TYPE_ENV_VARIABLE, }; char *env_var; while ((env_var = tlv_packet_iterate_str(&i))) { char *env_val = getenv(normalize_env_var(env_var)); if (env_val) { struct tlv_packet *env = tlv_packet_new(TLV_TYPE_ENV_GROUP, 0); env = tlv_packet_add_str(env, TLV_TYPE_ENV_VARIABLE, env_var); env = tlv_packet_add_str(env, TLV_TYPE_ENV_VALUE, env_val); p = tlv_packet_add_child(p, env); } } return p; } struct tlv_packet *sys_config_getuid(struct tlv_handler_ctx *ctx) { struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); return tlv_packet_add_fmt(p, TLV_TYPE_USER_NAME, "uid=%d, gid=%d, euid=%d, egid=%d", getuid(), geteuid(), getgid(), getegid()); } struct tlv_packet *sys_config_sysinfo(struct tlv_handler_ctx *ctx) { struct mettle *m = ctx->arg; sigar_sys_info_t sys_info; if (sigar_sys_info_get(mettle_get_sigar(m), &sys_info) == -1) { return tlv_packet_response_result(ctx, errno); } struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); p = tlv_packet_add_str(p, TLV_TYPE_COMPUTER_NAME, mettle_get_fqdn(m)); p = tlv_packet_add_fmt(p, TLV_TYPE_OS_NAME, "%s (%s %s)", sys_info.description, sys_info.name, sys_info.version); p = tlv_packet_add_str(p, TLV_TYPE_ARCHITECTURE, sys_info.arch); return p; }
// Kill the `arecord` process struct tlv_packet *audio_mic_stop(struct tlv_handler_ctx *ctx) { if (arecord != NULL) { pclose(arecord); arecord = NULL; // So we don't try to `pclose` it again, put here as a safeguard } return tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); }
struct tlv_packet *webcam_list(struct tlv_handler_ctx *ctx) { struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); for (int i=0;i<10;i++) { int fd = camera_open(i); if (fd == -1) { continue; } struct v4l2_capability cap; int result = xioctl(fd, VIDIOC_QUERYCAP, &cap); if (result == -1) { if (errno == EINVAL) { break; } else { continue; } } if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { continue; } if (!(cap.capabilities & V4L2_CAP_STREAMING)) { continue; } p = tlv_packet_add_str(p, TLV_TYPE_WEBCAM_NAME, (const char*)cap.card); } return p; }
static struct tlv_packet *core_machine_id(struct tlv_handler_ctx *ctx) { struct mettle *m = ctx->arg; struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); return tlv_packet_add_fmt(p, TLV_TYPE_MACHINE_ID, "%s:%s", mettle_get_fqdn(m), mettle_get_machine_id(m)); }
static struct tlv_packet *core_get_session_guid(struct tlv_handler_ctx *ctx) { struct mettle *m = ctx->arg; struct tlv_dispatcher *td = mettle_get_tlv_dispatcher(m); const char *session_guid = tlv_dispatcher_get_session_guid(td); struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); return tlv_packet_add_raw(p, TLV_TYPE_SESSION_GUID, session_guid, SESSION_GUID_LEN); }
struct tlv_packet *webcam_stop(struct tlv_handler_ctx *ctx) { enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl(fd, VIDIOC_STREAMOFF, &type) == -1) { return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); } unsigned int i; for (i = 0; i < n_buffers; ++i) { if (munmap(buffers[i].start, buffers[i].length) == -1) { return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); } } free(buffers); close(fd); return tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); }
static struct tlv_packet *core_shutdown(struct tlv_handler_ctx *ctx) { struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); // We're done, allow main() to cleanup... struct mettle *m = ctx->arg; ev_break(mettle_get_loop(m), EVBREAK_ALL); return p; }
struct tlv_packet *webcam_start(struct tlv_handler_ctx *ctx) { uint32_t deviceIndex = 0; uint32_t quality = 0; tlv_packet_get_u32(ctx->req, TLV_TYPE_WEBCAM_INTERFACE_ID, &deviceIndex); tlv_packet_get_u32(ctx->req, TLV_TYPE_WEBCAM_QUALITY, &quality); int result = camera_open(deviceIndex - 1); if (result == -1) { return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); } result = camera_start(); if (result == -1) { return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); } return tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); }
// Read all lines in `/proc/asound/pcm` if one has the `capture` mode enabled, send it struct tlv_packet *audio_mic_list(struct tlv_handler_ctx *ctx) { struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); char *sound_device = NULL; size_t len = 0; ssize_t read = 0; FILE *proc_asound_pcm = fopen("/proc/asound/pcm", "r"); if (proc_asound_pcm == NULL) { return tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); } while ((read = getline(&sound_device, &len, proc_asound_pcm)) != -1) { if (strstr(sound_device, "capture") != NULL) { p = tlv_packet_add_str(p, TLV_TYPE_AUDIO_INTERFACE_NAME, sound_device); } } return p; }
static struct tlv_packet *core_set_uuid(struct tlv_handler_ctx *ctx) { size_t uuid_len = 0; struct mettle *m = ctx->arg; struct tlv_dispatcher *td = mettle_get_tlv_dispatcher(m); char *uuid = tlv_packet_get_raw(ctx->req, TLV_TYPE_UUID, &uuid_len); if (uuid && uuid_len) { tlv_dispatcher_set_uuid(td, uuid, uuid_len); } return tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); }
// Simply launch `arecord` on the given card ID, send sound to stdout struct tlv_packet *audio_mic_start(struct tlv_handler_ctx *ctx) { uint32_t device; tlv_packet_get_u32(ctx->req, TLV_TYPE_AUDIO_INTERFACE_ID, &device); device--; int rc = TLV_RESULT_FAILURE; char cmd[100]; sprintf(cmd, "arecord -D plughw:%d -q -f cd -t raw -r 11025 -c 1", device); arecord = popen(cmd, "r"); if (arecord != NULL) { rc = TLV_RESULT_SUCCESS; } return tlv_packet_response_result(ctx, rc); }
static struct tlv_packet *enumextcmd(struct tlv_handler_ctx *ctx) { struct mettle *m = ctx->arg; const char *extension = tlv_packet_get_str(ctx->req, TLV_TYPE_STRING); /* * When enumerating stdapi, send everything we know about so far */ if (extension == NULL || strcmp(extension, "stdapi") == 0) { extension = NULL; } struct tlv_dispatcher *td = mettle_get_tlv_dispatcher(m); struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); tlv_dispatcher_iter_extension_methods(td, extension, add_method, &p); return p; }
static struct tlv_packet *core_shutdown(struct tlv_handler_ctx *ctx) { struct tlv_packet *p = tlv_packet_response_result(ctx, TLV_RESULT_FAILURE); #ifdef SIGKILL /* * First try to kill ourselves with a signal */ raise(SIGKILL); #endif /* * Try to simply exit */ exit(0); /* * Finally, trigger a SIGSEGV */ void (*nada) (void) = NULL; nada(); return p; }
static struct tlv_packet *core_negotiate_tlv_encryption(struct tlv_handler_ctx *ctx) { return tlv_packet_response_result(ctx, TLV_RESULT_SUCCESS); }