static gboolean initialize_device(struct upnp_device_descriptor *device_def, struct upnp_device *result_device, const char *ip_address, unsigned short port) { int rc; char *buf; rc = UpnpInit(ip_address, port); if (UPNP_E_SUCCESS != rc) { Log_error("upnp", "UpnpInit(ip=%s, port=%d) Error: %s (%d)", ip_address, port, UpnpGetErrorMessage(rc), rc); return FALSE; } Log_info("upnp", "Registered IP=%s port=%d\n", UpnpGetServerIpAddress(), UpnpGetServerPort()); rc = UpnpEnableWebserver(TRUE); if (UPNP_E_SUCCESS != rc) { Log_error("upnp", "UpnpEnableWebServer() Error: %s (%d)", UpnpGetErrorMessage(rc), rc); return FALSE; } if (!webserver_register_callbacks()) return FALSE; rc = UpnpAddVirtualDir("/upnp"); if (UPNP_E_SUCCESS != rc) { Log_error("upnp", "UpnpAddVirtualDir() Error: %s (%d)", UpnpGetErrorMessage(rc), rc); return FALSE; } buf = upnp_create_device_desc(device_def); rc = UpnpRegisterRootDevice2(UPNPREG_BUF_DESC, buf, strlen(buf), 1, &event_handler, result_device, &(result_device->device_handle)); free(buf); if (UPNP_E_SUCCESS != rc) { Log_error("upnp", "UpnpRegisterRootDevice2() Error: %s (%d)", UpnpGetErrorMessage(rc), rc); return FALSE; } rc = UpnpSendAdvertisement(result_device->device_handle, 100); if (UPNP_E_SUCCESS != rc) { Log_error("unpp", "Error sending advertisements: %s (%d)", UpnpGetErrorMessage(rc), rc); return FALSE; } return TRUE; }
static int output_ffmpeg_stop(void) { Log_error("ffmpeg", "output_ffmpeg_stop "); if (s_pthread_id) { s_Exit_Flag = TRUE; if (get_current_player_state() == FFMPEG_STATE_PAUSED) { wakeup_pause_status(); } pthread_join(s_pthread_id,NULL); s_Exit_Flag = FALSE; Log_error("ffmpeg", "output_ffmpeg_stop 2"); s_pthread_id = NULL; } return 0; }
static int get(struct RandomSeed* rs, uint64_t buffer[8]) { struct RandomSeed_pvt* ctx = Identity_check((struct RandomSeed_pvt*) rs); Log_info(ctx->logger, "Attempting to seed random number generator"); // each provider overwrites input and output is a rolling hash. struct RandomSeed_Buffer buff = { .output = {0} }; int successCount = 0; for (int i = 0; i < ctx->rsCount; i++) { if (!ctx->rsList[i]->get(ctx->rsList[i], buff.input)) { Log_info(ctx->logger, "Trying random seed [%s] Success", ctx->rsList[i]->name); crypto_hash_sha512((uint8_t*)buff.output, (uint8_t*)&buff, RandomSeed_Buffer_SIZE); successCount++; } else { Log_info(ctx->logger, "Trying random seed [%s] Failed", ctx->rsList[i]->name); } } Assert_true(sizeof(buff.output) == 64); Bits_memcpy(buffer, buff.output, 64); if (successCount > 0) { Log_info(ctx->logger, "Seeding random number generator succeeded with [%d] sources", successCount); return 0; } else { Log_error(ctx->logger, "Seeding random number generator failed"); return -1; } }
/* * Exported function implementations */ kern_return_t Task_createWithTask(Task* self, task_t task) { kern_return_t retVal = KERN_INVALID_ARGUMENT; if (self == NULL || task == TASK_NULL) { Log_invalidArgument("self: %p, task: %p", self, (void*) task); } else { pid_t pid = -1; (void) pid_for_task(task, &pid); cpu_type_t cpuType = getCPUTypeForTask(pid); if (cpuType == CPU_TYPE_ARM) { printf("ARM; NOT IMPLEMENTED\n"); //self->arch = TaskArch_ARM_create(); } else if (cpuType == CPU_TYPE_I386 || cpuType == CPU_TYPE_X86) { self->arch = TaskArch_x86_create(); } else if (cpuType == CPU_TYPE_X86_64) { self->arch = TaskArch_x86_64_create(); } else { Log_error("Unsupported process architecture, %d", cpuType); retVal = KERN_FAILURE; } if (self->arch) { self->task = task; self->pid = pid; self->cpuType = cpuType; self->wordSize = getWordSize(pid); retVal = KERN_SUCCESS; } } return retVal; }
static int output_ffmpeg_play(output_transition_cb_t callback) { Log_error("ffmpeg", "--play-- \n\n"); int ret = 0; play_trans_callback_ = callback; if (s_pthread_id) { //如果,己经开启了,说明是正在暂停! if (get_current_player_state() == FFMPEG_STATE_PAUSED) { wakeup_pause_status(); return 0; } } s_Exit_Flag = FALSE; // 创建线程 ret = pthread_create(&s_pthread_id,NULL,(void *) run_function,NULL); if(ret!=0) { printf("Create pthread error!\n"); return ; } return 0; }
static int output_ffmpeg_init(void) { Log_error("ffmpeg", "output_ffmpeg_init----- "); SongMetaData_init(&song_meta_); register_mime_type("audio/*"); register_mime_type("audio/x-mpeg"); register_mime_type("audio/mpeg"); av_register_all(); avformat_network_init(); //:(s_pFormatCtx = avformat_alloc_context(); s_au_convert_ctx = swr_alloc(); s_out_buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2); s_pFrame = av_frame_alloc(); mp_msg_init(); char ** ao_list= malloc(sizeof(char*)*2); const int c_number_count = 10; *ao_list = malloc(sizeof(char) * c_number_count); ao_list[1] = malloc(sizeof(char) *c_number_count); strcpy(ao_list[0],"alsa"); memset(ao_list[1],0, c_number_count); s_audio_device = init_best_audio_out(ao_list, 0, 44100, 2,AF_FORMAT_S16_LE,0); assert(s_audio_device != NULL); free(ao_list[0]); free(ao_list[1]); free(ao_list); mixer_Init_control_point(&s_mixer, s_audio_device); pthread_mutex_init(&s_mutex, NULL); pthread_cond_init(&s_cond, NULL); return 0; }
static int output_ffmpeg_get_mute(int *m) { gboolean val=TRUE; Log_error("ffmpeg", "Set mute to %s", m ? "on" : "off"); *m = val; return 0; }
static int output_ffmpeg_get_volume(float *v) { float volume = 0.0f; mixer_getbothvolume(&s_mixer, &volume); Log_error("ffmpeg", "Query volume fraction: %f", volume); *v = volume; return 0; }
gboolean webserver_register_callbacks(void) { int rc = UpnpSetVirtualDirCallbacks(&virtual_dir_callbacks); if (UPNP_E_SUCCESS != rc) { Log_error("webserver", "UpnpSetVirtualDirCallbacks() Error: %s (%d)", UpnpGetErrorMessage(rc), rc); return FALSE; } return TRUE; }
static int output_ffmpeg_seek(gint64 position_nanos) { Log_error("ffmpeg", "seek = %lld ", position_nanos); pthread_mutex_lock(&s_mutex); s_Seek_Flag = TRUE; s_want_to_seek_position = position_nanos; pthread_mutex_unlock(&s_mutex); return 0; }
int output_init(const char *shortname) { int count; count = sizeof(modules) / sizeof(struct output_module *); if (count == 0) { Log_error("output", "No output module available"); return -1; } if (shortname == NULL) { output_module = modules[0]; } else { int i; for (i=0; i<count; i++) { if (strcmp(modules[i]->shortname, shortname)==0) { output_module = modules[i]; break; } } } if (output_module == NULL) { Log_error("error", "ERROR: No such output module: '%s'", shortname); return -1; } Log_info("output", "Using output module: %s (%s)", output_module->shortname, output_module->description); output_module->shared_metadata = shared_metadata_create(); pthread_t thread; pthread_create(&thread, NULL, thread_update_track_time, NULL); if (output_module->init) { return output_module->init(); } return 0; }
static int output_ffmpeg_deinit(void) { av_frame_free(&s_pFrame); swr_free(&s_au_convert_ctx); av_free(s_out_buffer); Log_error("ffmpeg", "output_ffmpeg_deinit 1"); pthread_mutex_destroy(&s_mutex); Log_error("ffmpeg", "output_ffmpeg_deinit 2"); if (s_pthread_id) { pthread_join(s_pthread_id,NULL); Log_error("ffmpeg", "output_ffmpeg_deinit 3"); s_pthread_id = NULL; } return 0; }
// only in parent static void inFromChild(evutil_socket_t socket, short eventType, void* vcontext) { struct Admin* admin = (struct Admin*) vcontext; uint8_t buffer[MAX_API_REQUEST_SIZE]; ssize_t amount = read(admin->inFd, buffer, MAX_API_REQUEST_SIZE); if (amount < 1) { if (amount == 0 || errno != EAGAIN) { if (amount < 0) { Log_error1(admin->logger, "Broken pipe to admin process, errno=%d", errno); } else { Log_error(admin->logger, "Connection to admin process closed unexpectedly"); } event_free(admin->pipeEv); } return; } if (!admin->initialized) { if (amount != sizeof(struct sockaddr_storage) + sizeof(int) + 8) { Log_error(admin->logger, "unexpected length"); } else if (memcmp(buffer, "abcd", 4)) { Log_error(admin->logger, "bad magic"); } else if (memcmp(&buffer[sizeof(struct sockaddr_storage) + sizeof(int) + 4], "wxyz", 4)) { Log_error(admin->logger, "bad magic"); } else { Bits_memcpyConst(&admin->addressLength, &buffer[4], sizeof(int)); Bits_memcpyConst(&admin->address, &buffer[4 + sizeof(int)], sizeof(struct sockaddr_storage)); admin->initialized = true; } event_base_loopbreak(admin->eventBase); return; } struct Allocator* tempAllocator = admin->allocator->child(admin->allocator); handleRequestFromChild(admin, buffer, amount, tempAllocator); tempAllocator->free(tempAllocator); }
/** Called when the request allocator is freed. */ static int removeReqFromSet(struct Allocator_OnFreeJob* job) { struct Request* req = Identity_check((struct Request*) job->userData); struct Hermes* h = Identity_check(req->hermes); int index = Map_RequestSet_indexForHandle(req->handle, &h->requestSet); if (index > -1) { Map_RequestSet_remove(index, &h->requestSet); } else { Log_error(h->logger, "request with handle [%u] missing from set", req->handle); } return 0; }
/** * Doesn't read more than maxRead bytes into buf[*have..bufSize] * Increments *have by amount of read bytes * * Buffer mustn't be full, and maxRead > 0 * * return values: * n>0: read n new bytes * -1: eof/network or read error - closed * -2: EAGAIN */ static int inFromChildFillBuffer(struct Admin* admin, void *buf, uint32_t bufSize, uint32_t* have, uint32_t maxRead) { char *charBuf = (char*) buf; Assert_true(*have < bufSize); Assert_true(maxRead > 0); if (maxRead > bufSize - *have) { maxRead = bufSize - *have; } Assert_always(maxRead > 0); Assert_always(maxRead <= INT_MAX); errno = 0; ssize_t amount = read(admin->inFd, charBuf + *have, maxRead); if (amount < 0 && (EAGAIN == errno || EWOULDBLOCK == errno)) { return -2; } else if (0 == amount) { Log_error(admin->logger, "Connection to admin process closed unexpectedly"); adminClosePipes(admin); return -1; } else if (amount < 0) { Log_error(admin->logger, "Broken pipe to admin process, [%s]", strerror(errno)); adminClosePipes(admin); return -1; } Assert_always(amount > 0); Assert_true(amount <= (ssize_t) maxRead); *have += amount; Assert_true(*have <= bufSize); return amount; }
static void inFromChildInitialize(struct Admin* admin) { uint8_t buffer[sizeof(struct sockaddr_storage) + sizeof(int) + 8]; ssize_t amount = read(admin->inFd, buffer, sizeof(buffer)); if (amount != sizeof(buffer)) { Log_error(admin->logger, "unexpected length"); adminClosePipes(admin); } else if (memcmp(buffer, "abcd", 4)) { Log_error(admin->logger, "bad magic"); adminClosePipes(admin); } else if (memcmp(&buffer[sizeof(struct sockaddr_storage) + sizeof(int) + 4], "wxyz", 4)) { Log_error(admin->logger, "bad magic"); adminClosePipes(admin); } else { Bits_memcpyConst(&admin->addressLength, &buffer[4], sizeof(int)); Bits_memcpyConst(&admin->address, &buffer[4 + sizeof(int)], sizeof(struct sockaddr_storage)); admin->initialized = true; } event_base_loopbreak(admin->eventBase); }
void upnp_set_error(struct action_event *event, int error_code, const char *format, ...) { event->status = -1; va_list ap; va_start(ap, format); event->request->ActionResult = NULL; event->request->ErrCode = UPNP_SOAP_E_ACTION_FAILED; vsnprintf(event->request->ErrStr, sizeof(event->request->ErrStr), format, ap); va_end(ap); Log_error("upnp", "%s: %s\n", __FUNCTION__, event->request->ErrStr); }
static void ethInterfaceSetBeacon(int ifNum, Dict* eth, struct Context* ctx) { int64_t* beaconP = Dict_getInt(eth, String_CONST("beacon")); if (beaconP) { int64_t beacon = *beaconP; if (beacon > 3 || beacon < 0) { Log_error(ctx->logger, "interfaces.ETHInterface.beacon may only be 0, 1,or 2"); } else { // We can cast beacon to an int here because we know it's small enough Log_info(ctx->logger, "Setting beacon mode on ETHInterface to [%d].", (int) beacon); Dict d = Dict_CONST(String_CONST("interfaceNumber"), Int_OBJ(ifNum), Dict_CONST(String_CONST("state"), Int_OBJ(beacon), NULL)); rpcCall(String_CONST("ETHInterface_beacon"), &d, ctx, ctx->alloc); } } }
kern_return_t Exception_assign(Exception* self, mach_port_t task, mach_port_t thread, thread_state_t state, exception_type_t type, mach_exception_data_t code, mach_msg_type_number_t codeCnt) { kern_return_t retVal = KERN_FAILURE; if ( (self == NULL) || (task == TASK_NULL) || (thread == THREAD_NULL) || (state == NULL)) { Log_invalidArgument("self: %p, task: %p, thread: %p, state: %p", self, (void*) task, (void*) thread, state); } else { self->task = task; self->thread = thread; self->state = state; self->type = type; if (codeCnt > self->maxCount) { // resize data self->data = reallocf(self->data, codeCnt * sizeof(mach_exception_data_t)); if (self->data) { self->maxCount = codeCnt; } } if (self->data == NULL) { Log_error("unable to allcoate memory"); } else { self->count = codeCnt; (void) memcpy(self->data, code, self->count); retVal = KERN_SUCCESS; } } return retVal; }
// only in parent static void inFromChildRead(struct Admin* admin, struct Admin_Channel* channel) { Assert_true(admin->messageHeader.length > 0); if (!channel->buffer) { Assert_true(NULL == channel->allocator); channel->allocator = admin->allocator->child(admin->allocator); channel->buffer = channel->allocator->malloc(MAX_API_REQUEST_SIZE, channel->allocator); Assert_true(0 == channel->bufferLen); } Assert_true(channel->bufferLen < MAX_API_REQUEST_SIZE); int amount = inFromChildFillBuffer(admin, channel->buffer, MAX_API_REQUEST_SIZE, &channel->bufferLen, admin->messageHeader.length); if (amount < 0) { return; } admin->messageHeader.length -= amount; if (0 == admin->messageHeader.length) { admin->haveMessageHeaderLen = 0; } inFromChildDecode(admin, channel); if (MAX_API_REQUEST_SIZE == channel->bufferLen) { // couldn't decode the request, but the buffer is full Log_error(admin->logger, "Request too large, closing channel [%u]", admin->messageHeader.channelNum); adminChannelClose(admin, admin->messageHeader.channelNum); } if (0 == channel->bufferLen && channel->allocator) { // reached end of buffer, free it channel->allocator->free(channel->allocator); channel->allocator = NULL; channel->buffer = NULL; } }
static int event_handler(Upnp_EventType EventType, void *event, void *userdata) { struct upnp_device *priv = (struct upnp_device *) userdata; switch (EventType) { case UPNP_CONTROL_ACTION_REQUEST: handle_action_request(priv, event); break; case UPNP_CONTROL_GET_VAR_REQUEST: handle_var_request(priv, event); break; case UPNP_EVENT_SUBSCRIPTION_REQUEST: handle_subscription_request(priv, event); break; default: Log_error("upnp", "Unknown event type: %d", EventType); break; } return 0; }
static UpnpWebFileHandle webserver_open(const char *filename, enum UpnpOpenFileMode mode) { if (mode != UPNP_READ) { Log_error("webserver", "%s: ignoring request to open file for writing.", filename); return NULL; } for (struct virtual_file *vf = virtual_files; vf; vf = vf->next) { if (strcmp(filename, vf->virtual_fname) == 0) { WebServerFile *file = malloc(sizeof(WebServerFile)); file->pos = 0; file->len = vf->len; file->contents = vf->contents; return file; } } return NULL; }
int output_gstreamer_init_master(void) { GstBus *bus; GstElement *queue0; GstElement *decode_bin; GstElement *audio_sink0; player_ = gst_pipeline_new("audio_player_master"); gst_data.source = gst_element_factory_make ("souphttpsrc", "source"); gst_data.tee = gst_element_factory_make ("tee", "tee"); queue0 = gst_element_factory_make ("queue", "queue"); decode_bin = gst_element_factory_make ("decodebin", "decode_bin"); gst_data.convert = gst_element_factory_make("audioconvert", "convert"); audio_sink0 = gst_element_factory_make ("autoaudiosink", "audio_sink"); if (!player_ || !gst_data.source || !gst_data.tee || !queue0 || !decode_bin || !gst_data.convert || !audio_sink0) { g_print ("Not all elements could be created.\n"); } gst_bin_add_many (GST_BIN (player_), gst_data.source, gst_data.tee, queue0, decode_bin, gst_data.convert, audio_sink0, NULL); if (gst_element_link_many (gst_data.source, gst_data.tee, NULL) != TRUE) { g_print ("Elements could not be linked. 1\n"); //gst_object_unref (player_); } if (gst_element_link_many (gst_data.tee, queue0, decode_bin, NULL) != TRUE) { g_print ("Elements could not be linked. 2\n"); //gst_object_unref (player_); } if (gst_element_link_many (gst_data.convert, audio_sink0, NULL) != TRUE) { g_print ("Elements could not be linked. 3\n"); //gst_object_unref (player_); } g_signal_connect (decode_bin, "pad-added", G_CALLBACK (master_pad_added_handler), NULL); bus = gst_pipeline_get_bus(GST_PIPELINE(player_)); gst_bus_add_watch(bus, my_bus_callback, NULL); gst_object_unref(bus); if (audio_sink != NULL) { GstElement *sink = NULL; Log_info("gstreamer", "Setting audio sink to %s; device=%s\n", audio_sink, audio_device ? audio_device : ""); sink = gst_element_factory_make (audio_sink, "sink"); if (sink == NULL) { Log_error("gstreamer", "Couldn't create sink '%s'", audio_sink); } else { if (audio_device != NULL) { g_object_set (G_OBJECT(sink), "device", audio_device, NULL); } g_object_set (G_OBJECT (player_), "audio-sink", sink, NULL); } } if (videosink != NULL) { GstElement *sink = NULL; Log_info("gstreamer", "Setting video sink to %s", videosink); sink = gst_element_factory_make (videosink, "sink"); g_object_set (G_OBJECT (player_), "video-sink", sink, NULL); } if (gst_element_set_state(player_, GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) { Log_error("gstreamer", "Error: pipeline doesn't become ready."); } return 0; }
int main (int argc, char**argv) { int ret = 0; int heartbeat_usec = 50000; //20Hz is ok by default uint64_t last_beat = 0; Log_info ("cloudvpn starting"); Log (0, "You are using CloudVPN, which is Free software."); Log (0, "For more information please see the GNU GPL license,"); Log (0, "which you should have received along with this program."); setup_sighandler (kill_cloudvpn); /* * initialization */ if (!config_parse (argc, argv) ) { Log_error ("failed to parse config, terminating."); ret = 1; goto failed_config; } if (!config_get_int ("heartbeat", heartbeat_usec) ) heartbeat_usec = 50000; Log_info ("heartbeat is set to %d usec", heartbeat_usec); timestamp_update(); //get initial timestamp status_init(); route_init(); squeue_init(); network_init(); if (poll_init() ) { Log_fatal ("poll initialization failed"); ret = 2; goto failed_poll; } if (do_memlock() ) { Log_fatal ("locking process to memory failed"); ret = 3; goto failed_poll; } if (comm_load() ) { Log_fatal ("failed to load comm data"); ret = 4; goto failed_poll; } if (comm_init() ) { Log_fatal ("communication initialization failed"); ret = 5; goto failed_comm; } if (gate_init() ) { Log_fatal ("gate initialization failed"); ret = 6; goto failed_gate; } if (do_chroot() ) { Log_fatal ("chrooting failed"); ret = 7; goto failed_sec; } if (do_switch_user() ) { Log_fatal ("user switch failed"); ret = 8; goto failed_sec; } /* * main loop */ Log_info ("initialization complete, entering main loop"); last_beat = 0; //update immediately. while (!g_terminate) { timestamp_update(); if ( (timestamp() - last_beat) < (unsigned int) heartbeat_usec) { //poll more stuff poll_wait_for_event (heartbeat_usec - timestamp() + last_beat); //send the results comm_flush_data(); gate_flush_data(); continue; } last_beat = timestamp(); gate_periodic_update(); comm_periodic_update(); route_periodic_update(); status_try_export(); } /* * deinitialization */ Log_info ("shutting down"); failed_sec: gate_shutdown(); failed_gate: comm_shutdown(); failed_comm: if (poll_deinit() ) Log_warn ("poll_deinit somehow failed!"); failed_poll: failed_config: if (!ret) Log_info ("cloudvpn exiting gracefully"); else Log_error ("cloudvpn exiting with code %d", ret); return ret; }
int main(int argc, char **argv) { int rc; struct upnp_device_descriptor *upnp_renderer; if (!process_cmdline(argc, argv)) { return EXIT_FAILURE; } if (show_version) { do_show_version(); exit(EXIT_SUCCESS); } if (show_connmgr_scpd) { upnp_renderer_dump_connmgr_scpd(); exit(EXIT_SUCCESS); } if (show_control_scpd) { upnp_renderer_dump_control_scpd(); exit(EXIT_SUCCESS); } if (show_transport_scpd) { upnp_renderer_dump_transport_scpd(); exit(EXIT_SUCCESS); } if (show_outputs) { output_dump_modules(); exit(EXIT_SUCCESS); } init_logging(log_file); // Now we're going to start threads etc, which means we need // to become a daemon before that. // We need to open the pid-file now because relative filenames will // break if we're becoming a daemon and cwd changes. FILE *pid_file_stream = NULL; if (pid_file) { pid_file_stream = fopen(pid_file, "w"); } if (daemon_mode) { daemon(0, 0); // TODO: check for daemon() in configure. } if (pid_file_stream) { fprintf(pid_file_stream, "%d\n", getpid()); fclose(pid_file_stream); } #if !GLIB_CHECK_VERSION(2, 32, 0) // Only older version of glib require this. if (!g_thread_get_initialized()) { g_thread_init(NULL); } #endif upnp_renderer = upnp_renderer_descriptor(friendly_name, uuid); if (upnp_renderer == NULL) { return EXIT_FAILURE; } rc = output_init(output); if (rc != 0) { Log_error("main", "ERROR: Failed to initialize Output subsystem"); return EXIT_FAILURE; } struct upnp_device *device; if (listen_port != 0 && (listen_port < 49152 || listen_port > 65535)) { // Somewhere obscure internally in libupnp, they clamp the // port to be outside of the IANA range, so at least 49152. // Instead of surprising the user by ignoring lower port // numbers, complain loudly. Log_error("main", "Parameter error: --port needs to be in " "range [49152..65535] (but was set to %d)", listen_port); return EXIT_FAILURE; } device = upnp_device_init(upnp_renderer, ip_address, listen_port); if (device == NULL) { Log_error("main", "ERROR: Failed to initialize UPnP device"); return EXIT_FAILURE; } upnp_transport_init(device); upnp_control_init(device); if (show_devicedesc) { // This can only be run after all services have been // initialized. char *buf = upnp_create_device_desc(upnp_renderer); assert(buf != NULL); fputs(buf, stdout); exit(EXIT_SUCCESS); } if (Log_info_enabled()) { upnp_transport_register_variable_listener(log_variable_change, (void*) "transport"); upnp_control_register_variable_listener(log_variable_change, (void*) "control"); } // Write both to the log (which might be disabled) and console. Log_info("main", "Ready for rendering."); fprintf(stderr, "Ready for rendering.\n"); output_loop(); // We're here, because the loop exited. Probably due to catching // a signal. Log_info("main", "Exiting."); upnp_device_shutdown(device); return EXIT_SUCCESS; }
int main(int argc, char **argv) { int rc; struct upnp_device_descriptor *upnp_renderer; #if !GLIB_CHECK_VERSION(2,32,0) g_thread_init (NULL); // Was necessary < glib 2.32, deprecated since. #endif if (!process_cmdline(argc, argv)) { return EXIT_FAILURE; } if (show_version) { do_show_version(); exit(EXIT_SUCCESS); } if (show_connmgr_scpd) { upnp_renderer_dump_connmgr_scpd(); exit(EXIT_SUCCESS); } if (show_control_scpd) { upnp_renderer_dump_control_scpd(); exit(EXIT_SUCCESS); } if (show_transport_scpd) { upnp_renderer_dump_transport_scpd(); exit(EXIT_SUCCESS); } if (show_outputs) { output_dump_modules(); exit(EXIT_SUCCESS); } init_logging(log_file); // Now we're going to start threads etc, which means we need // to become a daemon before that. // We need to open the pid-file now because relative filenames will // break if we're becoming a daemon and cwd changes. FILE *pid_file_stream = NULL; if (pid_file) { pid_file_stream = fopen(pid_file, "w"); } if (daemon_mode) { daemon(0, 0); // TODO: check for daemon() in configure. } if (pid_file_stream) { fprintf(pid_file_stream, "%d\n", getpid()); fclose(pid_file_stream); } if (show_devicedesc) { // This can only be run after all services have been // initialized. char *buf = upnp_create_device_desc(upnp_renderer); assert(buf != NULL); fputs(buf, stdout); exit(EXIT_SUCCESS); } struct upnp *upnp = upnp_start(friendly_name, uuid, "1234", ip_address, listen_port, output); if (upnp == NULL) { Log_error("main", "ERROR: Failed to initialize UPnP device"); return EXIT_FAILURE; } // Write both to the log (which might be disabled) and console. Log_info("main", "Ready for rendering."); fprintf(stderr, "Ready for rendering.\n"); output_loop(); // We're here, because the loop exited. Probably due to catching // a signal. Log_info("main", "Exiting."); upnp_stop(upnp); return EXIT_SUCCESS; }
static void runTest0(char** prefixes, char** exceptions4, char** exceptions6, char** expectedOut4, char** expectedOut6, struct Allocator* alloc, struct Log* log) { struct RouteGen* rg = RouteGen_new(alloc, log); for (int i = 0; prefixes[i]; i++) { RouteGen_addPrefix(rg, mkSockaddr(prefixes[i], alloc)); } for (int i = 0; exceptions4 && exceptions4[i]; i++) { RouteGen_addException(rg, mkSockaddr(exceptions4[i], alloc)); } for (int i = 0; exceptions6 && exceptions6[i]; i++) { RouteGen_addException(rg, mkSockaddr(exceptions6[i], alloc)); } Dict* routes = RouteGen_getGeneratedRoutes(rg, alloc); List* routes4 = Dict_getList(routes, String_CONST("ipv4")); List* routes6 = Dict_getList(routes, String_CONST("ipv6")); if (expectedOut4) { for (int i = 0; expectedOut4[i]; i++) { Log_debug(log, "%s\n", expectedOut4[i]); } for (int i = 0; i < List_size(routes4); i++) { Log_debug(log, "%s\n", List_getString(routes4, i)->bytes); } Assert_true(!expectedOut4[List_size(routes4)]); for (int i = 0; i < List_size(routes4); i++) { String* str = List_getString(routes4, i); Assert_true(str); Assert_true(expectedOut4[i]); if (CString_strncmp(expectedOut4[i], str->bytes, str->len)) { Log_error(log, "Fail\nexpected: %s\nGot: %s\n", expectedOut4[i], str->bytes); Assert_failure("fail"); } } } else { Assert_true(!List_size(routes4)); } if (expectedOut6) { for (int i = 0; expectedOut6[i]; i++) { Log_debug(log, "%s\n", expectedOut6[i]); } for (int i = 0; i < List_size(routes6); i++) { Log_debug(log, "%s\n", List_getString(routes6, i)->bytes); } Assert_true(!expectedOut6[List_size(routes6)]); for (int i = 0; i < List_size(routes6); i++) { String* str = List_getString(routes6, i); Assert_true(str); Assert_true(expectedOut6[i]); if (CString_strncmp(expectedOut6[i], str->bytes, str->len)) { Log_error(log, "Fail\nexpected: %s\nGot: %s\n", expectedOut6[i], str->bytes); Assert_failure("fail"); } } } else { Assert_true(!List_size(routes6)); } }
// only in parent static void inFromChild(evutil_socket_t socket, short eventType, void* vcontext) { struct Admin* admin = (struct Admin*) vcontext; if (!admin->initialized) { inFromChildInitialize(admin); return; } int newMessage = 0; if (admin->haveMessageHeaderLen < Admin_MessageHeader_SIZE) { int amount = inFromChildFillBuffer(admin, &admin->messageHeader, Admin_MessageHeader_SIZE, &admin->haveMessageHeaderLen, Admin_MessageHeader_SIZE); if (amount < 0) { return; } if (admin->haveMessageHeaderLen == Admin_MessageHeader_SIZE) { newMessage = 1; // got complete header if (admin->pipeMagic != admin->messageHeader.magic) { Log_error(admin->logger, "wrong magic from admin process"); adminClosePipes(admin); return; } if (admin->messageHeader.length > MAX_MESSAGE_SIZE) { Log_error(admin->logger, "message from admin process too large"); adminClosePipes(admin); return; } if (0 == admin->messageHeader.length) { // empty message -> close channel adminChannelHandleClose(admin); admin->haveMessageHeaderLen = 0; return; } } } if (admin->haveMessageHeaderLen == Admin_MessageHeader_SIZE) { // handle non empty message data struct Admin_Channel* channel = adminChannelFindById(admin, admin->messageHeader.channelNum); if (!channel) { if (newMessage) { Log_info(admin->logger, "message from admin process on invalid channel [%u]", admin->messageHeader.channelNum); // send close adminChannelSendData(admin, admin->messageHeader.channelNum, NULL, 0); } /* ignore data */ inFromChildSkipMmsg(admin); } else { switch (channel->state) { case Admin_ChannelState_CLOSED: channel->state = Admin_ChannelState_OPEN; inFromChildRead(admin, channel); break; case Admin_ChannelState_OPEN: inFromChildRead(admin, channel); break; case Admin_ChannelState_WAIT_FOR_CLOSE: /* ignore data */ inFromChildSkipMmsg(admin); break; } } } }
static int handle_subscription_request(struct upnp_device *priv, struct Upnp_Subscription_Request *sr_event) { struct service *srv; int rc; assert(priv != NULL); Log_info("upnp", "Subscription request for %s (%s)", sr_event->ServiceId, sr_event->UDN); srv = find_service(priv->upnp_device_descriptor, sr_event->ServiceId); if (srv == NULL) { Log_error("upnp", "%s: Unknown service '%s'", __FUNCTION__, sr_event->ServiceId); return -1; } int result = -1; ithread_mutex_lock(&(priv->device_mutex)); // There is really only one variable evented: LastChange const char *eventvar_names[] = { "LastChange", NULL }; const char *eventvar_values[] = { NULL, NULL }; // Build the current state of the variables as one gigantic initial // LastChange update. ithread_mutex_lock(srv->service_mutex); const int var_count = VariableContainer_get_num_vars(srv->variable_container); // TODO(hzeller): maybe use srv->last_change directly ? upnp_last_change_builder_t *builder = UPnPLastChangeBuilder_new(srv->event_xml_ns); for (int i = 0; i < var_count; ++i) { const char *name; const char *value = VariableContainer_get(srv->variable_container, i, &name); // Send over all variables except "LastChange" itself. Also all // A_ARG_TYPE variables are not evented. if (value && strcmp("LastChange", name) != 0 && strncmp("A_ARG_TYPE_", name, strlen("A_ARG_TYPE_")) != 0) { UPnPLastChangeBuilder_add(builder, name, value); } } ithread_mutex_unlock(srv->service_mutex); char *xml_value = UPnPLastChangeBuilder_to_xml(builder); Log_info("upnp", "Initial variable sync: %s", xml_value); eventvar_values[0] = xmlescape(xml_value, 0); free(xml_value); UPnPLastChangeBuilder_delete(builder); rc = UpnpAcceptSubscription(priv->device_handle, sr_event->UDN, sr_event->ServiceId, eventvar_names, eventvar_values, 1, sr_event->Sid); if (rc == UPNP_E_SUCCESS) { result = 0; } else { Log_error("upnp", "Accept Subscription Error: %s (%d)", UpnpGetErrorMessage(rc), rc); } ithread_mutex_unlock(&(priv->device_mutex)); free((char*)eventvar_values[0]); return result; }
static int handle_action_request(struct upnp_device *priv, struct Upnp_Action_Request *ar_event) { struct service *event_service; struct action *event_action; event_service = find_service(priv->upnp_device_descriptor, ar_event->ServiceID); event_action = find_action(event_service, ar_event->ActionName); if (event_action == NULL) { Log_error("upnp", "Unknown action '%s' for service '%s'", ar_event->ActionName, ar_event->ServiceID); ar_event->ActionResult = NULL; ar_event->ErrCode = 401; return -1; } // We want to send the LastChange event only after the action is // finished - just to be conservative, we don't know how clients // react to get LastChange notifictions while in the middle of // issuing an action. // // So we nest the change collector level here, so that we only send the // LastChange after the action is finished (). // // Note, this is, in fact, only a preparation and not yet working as // described above: we are still in the middle // of executing the event-callback while sending the last change // event implicitly when calling UPnPLastChangeCollector_finish() below. // It would be good to enqueue the upnp_device_notify() after // the action event is finished. if (event_service->last_change) { ithread_mutex_lock(event_service->service_mutex); UPnPLastChangeCollector_start(event_service->last_change); ithread_mutex_unlock(event_service->service_mutex); } #ifdef ENABLE_ACTION_LOGGING { char *action_request_xml = NULL; if (ar_event->ActionRequest) { action_request_xml = ixmlDocumenttoString( ar_event->ActionRequest); } Log_info("upnp", "Action '%s'; Request: %s", ar_event->ActionName, action_request_xml); free(action_request_xml); } #endif if (event_action->callback) { struct action_event event; int rc; event.request = ar_event; event.status = 0; event.service = event_service; event.device = priv; rc = (event_action->callback) (&event); if (rc == 0) { ar_event->ErrCode = UPNP_E_SUCCESS; #ifdef ENABLE_ACTION_LOGGING if (ar_event->ActionResult) { char *action_result_xml = NULL; action_result_xml = ixmlDocumenttoString( ar_event->ActionResult); Log_info("upnp", "Action '%s' OK; Response %s", ar_event->ActionName, action_result_xml); free(action_result_xml); } else { Log_info("upnp", "Action '%s' OK", ar_event->ActionName); } #endif } if (ar_event->ActionResult == NULL) { ar_event->ActionResult = UpnpMakeActionResponse(ar_event->ActionName, event_service->service_type, 0, NULL); } } else { Log_error("upnp", "Got a valid action, but no handler defined (!)\n" " ErrCode: %d\n" " Socket: %d\n" " ErrStr: '%s'\n" " ActionName: '%s'\n" " DevUDN: '%s'\n" " ServiceID: '%s'\n", ar_event->ErrCode, ar_event->Socket, ar_event->ErrStr, ar_event->ActionName, ar_event->DevUDN, ar_event->ServiceID); ar_event->ErrCode = UPNP_E_SUCCESS; } if (event_service->last_change) { // See comment above. ithread_mutex_lock(event_service->service_mutex); UPnPLastChangeCollector_finish(event_service->last_change); ithread_mutex_unlock(event_service->service_mutex); } return 0; }