static int send_packet(struct rtmp_stream *stream, struct encoder_packet *packet, bool is_header, size_t idx) { uint8_t *data; size_t size; int recv_size = 0; int ret = 0; #ifdef _WIN32 ret = ioctlsocket(stream->rtmp.m_sb.sb_socket, FIONREAD, (u_long*)&recv_size); #else ret = ioctl(stream->rtmp.m_sb.sb_socket, FIONREAD, &recv_size); #endif if (ret >= 0 && recv_size > 0) { if (!discard_recv_data(stream, (size_t)recv_size)) return -1; } flv_packet_mux(packet, &data, &size, is_header); #ifdef TEST_FRAMEDROPS os_sleep_ms(rand() % 40); #endif ret = RTMP_Write(&stream->rtmp, (char*)data, (int)size, (int)idx); bfree(data); obs_free_encoder_packet(packet); stream->total_bytes_sent += size; return ret; }
static void *audio_thread(void *param) { struct audio_output *audio = param; uint64_t buffer_time = audio->info.buffer_ms * 1000000; uint64_t prev_time = os_gettime_ns() - buffer_time; uint64_t audio_time; os_set_thread_name("audio-io: audio thread"); const char *audio_thread_name = profile_store_name(obs_get_profiler_name_store(), "audio_thread(%s)", audio->info.name); while (os_event_try(audio->stop_event) == EAGAIN) { os_sleep_ms(AUDIO_WAIT_TIME); profile_start(audio_thread_name); pthread_mutex_lock(&audio->line_mutex); audio_time = os_gettime_ns() - buffer_time; audio_time = mix_and_output(audio, audio_time, prev_time); prev_time = audio_time; pthread_mutex_unlock(&audio->line_mutex); profile_end(audio_thread_name); profile_reenable_thread(); } return NULL; }
/*************PRIVATE FUNCTIONS ******************/ static RC_TYPE dyn_dns_wait_for_cmd(DYN_DNS_CLIENT *p_self) { int counter; DYN_DNS_CMD old_cmd; if (p_self == NULL) { return RC_INVALID_POINTER; } old_cmd = p_self->cmd; if (old_cmd != NO_CMD) { return RC_OK; } counter = p_self->sleep_sec / p_self->cmd_check_period; while (counter --) { if (p_self->cmd != old_cmd) { break; } os_sleep_ms(p_self->cmd_check_period * 1000); } return RC_OK; }
void Statistics::Start() { if (isStarted_) return; auto w = [this]() { int vCount = 0; //每一次循环加1 while(!quit_) { os_sleep_ms(1000); std::lock_guard<std::mutex> lock(mutex_); perSecond_[vCount % interval_] = curVideoStatByte_; vCount++; int base = vCount < interval_ ? vCount : interval_; int tmp = 0; for(int i = 0; i < interval_; i++) { tmp += perSecond_[i]; } statInfo_.videoBitrate = tmp / base; statInfo_.videoFps = videoFrameCount_; statInfo_.audioFps = audioFrameCount_; statInfo_.audioBitrate = curAudioStatByte_; curVideoStatByte_ = 0; curAudioStatByte_ = 0; videoFrameCount_ = 0; audioFrameCount_ = 0; } }; statThread = std::thread(w); isStarted_ = true; }
static int send_packet(struct rtmp_stream *stream, struct encoder_packet *packet, bool is_header, size_t idx) { uint8_t *data; size_t size; int ret = 0; flv_packet_mux(packet, &data, &size, is_header); #ifdef TEST_FRAMEDROPS os_sleep_ms(rand() % 40); #endif ret = RTMP_Write(&stream->rtmp, (char*)data, (int)size, (int)idx); bfree(data); obs_free_encoder_packet(packet); stream->total_bytes_sent += size; return ret; }
static void *audio_thread(void *param) { struct audio_output *audio = param; size_t rate = audio->info.samples_per_sec; uint64_t samples = 0; uint64_t start_time = os_gettime_ns(); uint64_t prev_time = start_time; uint64_t audio_time = prev_time; uint32_t audio_wait_time = (uint32_t)(audio_frames_to_ns(rate, AUDIO_OUTPUT_FRAMES) / 1000000); os_set_thread_name("audio-io: audio thread"); const char *audio_thread_name = profile_store_name(obs_get_profiler_name_store(), "audio_thread(%s)", audio->info.name); while (os_event_try(audio->stop_event) == EAGAIN) { uint64_t cur_time; os_sleep_ms(audio_wait_time); profile_start(audio_thread_name); cur_time = os_gettime_ns(); while (audio_time <= cur_time) { samples += AUDIO_OUTPUT_FRAMES; audio_time = start_time + audio_frames_to_ns(rate, samples); input_and_output(audio, audio_time, prev_time); prev_time = audio_time; } profile_end(audio_thread_name); profile_reenable_thread(); } return NULL; }
static void *audio_thread(void *param) { struct audio_output *audio = param; uint64_t buffer_time = audio->info.buffer_ms * 1000000; uint64_t prev_time = os_gettime_ns() - buffer_time; uint64_t audio_time; while (os_event_try(audio->stop_event) == EAGAIN) { os_sleep_ms(AUDIO_WAIT_TIME); pthread_mutex_lock(&audio->line_mutex); audio_time = os_gettime_ns() - buffer_time; audio_time = mix_and_output(audio, audio_time, prev_time); prev_time = audio_time; pthread_mutex_unlock(&audio->line_mutex); } return NULL; }
/*************PRIVATE FUNCTIONS ******************/ static int dyn_dns_wait_for_cmd(ddns_t *ctx) { int counter; ddns_cmd_t old_cmd; if (!ctx) return RC_INVALID_POINTER; old_cmd = ctx->cmd; if (old_cmd != NO_CMD) return 0; counter = ctx->sleep_sec / ctx->cmd_check_period; while (counter--) { if (ctx->cmd != old_cmd) break; os_sleep_ms(ctx->cmd_check_period * 1000); } return 0; }
void os_sleepto_ns(uint64_t time_target) { uint64_t t = os_gettime_ns(); uint32_t milliseconds; if (t >= time_target) return; milliseconds = (uint32_t)((time_target - t)/1000000); if (milliseconds > 1) os_sleep_ms(milliseconds); for (;;) { t = os_gettime_ns(); if (t >= time_target) return; #if 1 Sleep(1); #else Sleep(0); #endif } }
static RC_TYPE do_update_alias_table(DYN_DNS_CLIENT *p_self) { int i, j; RC_TYPE rc = RC_OK, rc2; HTTP_TRANSACTION http_tr; int anychange = 0; for (i = 0; i < p_self->info_count; i++) { DYNDNS_INFO_TYPE *info = &p_self->info[i]; for (j = 0; j < info->alias_count; j++) { if (info->alias_info[j].update_required != TRUE) { continue; } rc = http_client_init(&p_self->http_to_dyndns[i], "Sending IP# update to DDNS server"); if (rc != RC_OK) { break; } /* Build dyndns transaction */ http_tr.req_len = info->p_dns_system->p_dns_update_req_func( (struct _DYN_DNS_CLIENT*) p_self, i, j); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1; /* Save place for a \0 at the end */ http_tr.rsp_len = 0; rc = http_client_transaction(&p_self->http_to_dyndns[i], &http_tr); http_tr.p_rsp[http_tr.rsp_len] = 0; if (p_self->dbg.level > 2) { p_self->p_req_buffer[http_tr.req_len] = 0; logit(LOG_DEBUG, MODULE_TAG "Sending alias table update to DDNS server:"); logit(LOG_DEBUG, MODULE_TAG "%s", p_self->p_req_buffer); } if (rc == RC_OK) { rc = info->p_dns_system->p_rsp_ok_func((struct _DYN_DNS_CLIENT*)p_self, &http_tr, i); if (rc == RC_OK) { info->alias_info[j].update_required = FALSE; logit(LOG_INFO, MODULE_TAG "Successful alias table update for %s => new IP# %s", info->alias_info[j].names.name, info->my_ip_address.name); p_self->time_since_last_update = 0; anychange++; /* Adjust forced update period on success */ } else { logit(LOG_WARNING, MODULE_TAG "%s error in DDNS server response:", rc == RC_DYNDNS_RSP_RETRY_LATER ? "Temporary" : "Fatal"); logit(LOG_WARNING, MODULE_TAG "[%d %s] %s", http_tr.status, http_tr.status_desc, http_tr.p_rsp_body != http_tr.p_rsp ? http_tr.p_rsp_body : ""); } if (p_self->dbg.level > 2) { logit(LOG_DEBUG, MODULE_TAG "DDNS server response:"); logit(LOG_DEBUG, MODULE_TAG "%s", http_tr.p_rsp); } } rc2 = http_client_shutdown(&p_self->http_to_dyndns[i]); if (rc == RC_OK) { /* Only overwrite rc with of http_client_shutdown() rc if previous call, in * e.g., http_client_transaction() or the p_rsp_ok_func() callback was OK. */ rc = rc2; } if (rc != RC_OK) { break; } os_sleep_ms(1000); } } /* Successful change or when cache file does not yet exist! */ if (anychange || access(p_self->cachefile, F_OK)) { FILE *fp; /* Update cache with new IP */ fp = fopen(p_self->cachefile, "w"); if (fp) { fprintf(fp, "%s", p_self->info[0].my_ip_address.name); fclose(fp); } if (anychange && p_self->external_command) { /* Run external command hook on update. */ os_shell_execute(p_self->external_command); } } return rc; }
static RC_TYPE do_update_alias_table(DYN_DNS_CLIENT *p_self) { int i; int shutdown = 0; RC_TYPE rc = RC_OK; FILE *fp; do { for (i = 0; i < p_self->alias_info.count; ++i) { if (p_self->alias_info.update_required[i] != TRUE) { continue; } rc = http_client_init(&p_self->http_to_dyndns); if (rc != RC_OK) { break; } /*build dyndns transaction*/ { HTTP_TRANSACTION http_tr; http_tr.req_len = p_self->info.p_dns_system->p_dns_update_req_func( (struct _DYN_DNS_CLIENT*) p_self,i, (struct DYNDNS_SYSTEM*) p_self->info.p_dns_system); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1;/*save place for a \0 at the end*/ http_tr.rsp_len = 0; p_self->p_work_buffer[http_tr.rsp_len+1] = 0; /*send it*/ rc = http_client_transaction(&p_self->http_to_dyndns, &http_tr); if (p_self->dbg.level > 2) { p_self->p_req_buffer[http_tr.req_len] = 0; DBG_PRINTF((LOG_DEBUG,"DYNDNS my Request:\n%s\n", p_self->p_req_buffer)); } if (rc == RC_OK) { int rc = p_self->info.p_dns_system->p_rsp_ok_func((struct _DYN_DNS_CLIENT*)p_self, http_tr.p_rsp, p_self->info.p_dns_system->p_success_string); if (rc == RC_OK) { p_self->alias_info.update_required[i] = FALSE; DBG_PRINTF((LOG_WARNING,"I:" MODULE_TAG "Alias '%s' to IP '%s' updated successfully.\n", p_self->alias_info.names[i].name, p_self->info.my_ip_address.name)); p_self->times_since_last_update = 0; /*recalc forced update period*/ p_self->forced_update_period_sec = p_self->forced_update_period_sec_orig; p_self->forced_update_times = p_self->forced_update_period_sec / p_self->sleep_sec; if ((fp=fopen(p_self->ip_cache, "w"))) { fprintf(fp,"%s", p_self->info.my_ip_address.name); fclose(fp); } if ((fp=fopen(p_self->time_cache, "w"))) { fprintf(fp,"%ld", time (NULL)); fclose(fp); } if (strlen(p_self->external_command) > 0) os_shell_execute(p_self->external_command); } else { DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "Response Code: %d\n", rc)); DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "Error validating DYNDNS svr answer. Check usr,pass,hostname! (%s)\n", http_tr.p_rsp)); shutdown++; } if (p_self->dbg.level > 2) { http_tr.p_rsp[http_tr.rsp_len] = 0; DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "DYNDNS Server response:\n%s\n", http_tr.p_rsp)); } } } { RC_TYPE rc2 = http_client_shutdown(&p_self->http_to_dyndns); if (rc == RC_OK) { rc = rc2; } } if (rc != RC_OK || shutdown>2) { break; } os_sleep_ms(1000); } if (rc != RC_OK) { break; } } while(0); return rc; }
static RC_TYPE do_update_alias_table(DYN_DNS_CLIENT *p_self) { int i; RC_TYPE rc = RC_OK; do { for (i = 0; i < p_self->alias_info.count; ++i) { if (p_self->alias_info.update_required[i] != TRUE) { continue; } rc = http_client_init(&p_self->http_to_dyndns); if (rc != RC_OK) { break; } /*build dyndns transaction*/ { HTTP_TRANSACTION http_tr; http_tr.req_len = p_self->info.p_dns_system->p_dns_update_req_func( (struct _DYN_DNS_CLIENT*) p_self,i, (struct DYNDNS_SYSTEM*) p_self->info.p_dns_system); http_tr.p_req = (char*) p_self->p_req_buffer; http_tr.p_rsp = (char*) p_self->p_work_buffer; http_tr.max_rsp_len = p_self->work_buffer_size - 1;/*save place for a \0 at the end*/ http_tr.rsp_len = 0; p_self->p_work_buffer[http_tr.rsp_len+1] = 0; /*send it*/ rc = http_client_transaction(&p_self->http_to_dyndns, &http_tr); if (p_self->dbg.level > 2) { p_self->p_req_buffer[http_tr.req_len] = 0; DBG_PRINTF((LOG_DEBUG,"DYNDNS my Request:\n%s\n", p_self->p_req_buffer)); } if (rc == RC_OK) { BOOL update_ok = p_self->info.p_dns_system->p_rsp_ok_func((struct _DYN_DNS_CLIENT*)p_self, http_tr.p_rsp, p_self->info.p_dns_system->p_success_string); if (update_ok) { p_self->alias_info.update_required[i] = FALSE; DBG_PRINTF((LOG_WARNING,"I:" MODULE_TAG "Alias '%s' to IP '%s' updated successful.\n", p_self->alias_info.names[i].name, p_self->info.my_ip_address.name)); p_self->times_since_last_update = 0; } else { DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "Error validating DYNDNS svr answer. Check usr,pass,hostname!\n", http_tr.p_rsp)); } if (p_self->dbg.level > 2) { http_tr.p_rsp[http_tr.rsp_len] = 0; DBG_PRINTF((LOG_WARNING,"W:" MODULE_TAG "DYNDNS Server response:\n%s\n", http_tr.p_rsp)); } } } { RC_TYPE rc2 = http_client_shutdown(&p_self->http_to_dyndns); if (rc == RC_OK) { rc = rc2; } } if (rc != RC_OK) { break; } os_sleep_ms(1000); } if (rc != RC_OK) { break; } } while(0); return rc; }
int main(int argc, char* argv[]) { if (argc < 2) { puts("Serial port missing"); return 1; } if (argc < 3) { puts("Bluetooth address missing"); return 1; } uint8_t peerAddress[6]; if (! utl_parseAddress(argv[2], peerAddress)) { printf("Failed to parse input address: %s\n", argv[2]); return 1; } if (lb_initialize() < 0) { puts("Failed to initialize lightBLUE library"); return 2; } io_setDebugLevel(0); lb_setDebugLevel(0); struct LB_Controller* controller = lb_connect(argv[1]); if (! controller) { printf("Failed to connect to %s.\n", argv[1]); return 3; } if (LB_OK != lb_initializeHCI(controller)) { goto done; } if (LB_OK != lb_configureAsCentral(controller)) { goto done; } if (LB_OK != lb_openDeviceConnection(controller, peerAddress, &peerConnectionHandle)) { goto done; } printf("Connected to "); utl_printAddress(peerAddress); printf(" using: %p\n", peerConnectionHandle); puts("Waiting for events. Press Ctrl-C to quit."); os_waitForKeyboardInterrupt(); lb_closeDeviceConnection(peerConnectionHandle); os_sleep_ms(2000); done: lb_disconnect(controller); lb_cleanup(); return 0; }
static int do_update_alias_table(ddns_t *ctx) { int i, j; int rc = 0, rc2; http_trans_t http_tr; int anychange = 0; for (i = 0; i < ctx->info_count; i++) { ddns_info_t *info = &ctx->info[i]; for (j = 0; j < info->alias_count; j++) { if (info->alias[j].update_required != 1) { continue; } rc = http_client_init(&ctx->http_to_dyndns[i], "Sending IP# update to DDNS server"); if (rc != 0) { break; } /* Build dyndns transaction */ http_tr.req_len = info->system->update_request_func(ctx, i, j); http_tr.p_req = (char *)ctx->request_buf; http_tr.p_rsp = (char *)ctx->work_buf; http_tr.max_rsp_len = ctx->work_buflen - 1; /* Save place for a \0 at the end */ http_tr.rsp_len = 0; rc = http_client_transaction(&ctx->http_to_dyndns[i], &http_tr); http_tr.p_rsp[http_tr.rsp_len] = 0; if (ctx->dbg.level > 2) { ctx->request_buf[http_tr.req_len] = 0; logit(LOG_DEBUG, "Sending alias table update to DDNS server:"); logit(LOG_DEBUG, "%s", ctx->request_buf); } if (rc == 0) { rc = info->system->response_ok_func(ctx, &http_tr, i); if (rc == 0) { info->alias[j].update_required = 0; logit(LOG_INFO, "Successful alias table update for %s => new IP# %s", info->alias[j].names.name, info->my_ip_address.name); ctx->time_since_last_update = 0; ctx->force_addr_update = 0; anychange++; } else { logit(LOG_WARNING, "%s error in DDNS server response:", rc == RC_DYNDNS_RSP_RETRY_LATER ? "Temporary" : "Fatal"); logit(LOG_WARNING, "[%d %s] %s", http_tr.status, http_tr.status_desc, http_tr.p_rsp_body != http_tr.p_rsp ? http_tr.p_rsp_body : ""); } if (ctx->dbg.level > 2) { logit(LOG_DEBUG, "DDNS server response:"); logit(LOG_DEBUG, "%s", http_tr.p_rsp); } } rc2 = http_client_shutdown(&ctx->http_to_dyndns[i]); if (rc == 0) { /* Only overwrite rc with of http_client_shutdown() rc if previous call, in * e.g., http_client_transaction() or the response_ok_func() callback was OK. */ rc = rc2; } if (rc != 0) { break; } os_sleep_ms(1000); } } /* Successful change or when cache file does not yet exist! */ if (anychange || access(ctx->cache_file, F_OK)) { FILE *fp; /* Update cache with new IP */ fp = fopen(ctx->cache_file, "w"); if (fp) { fprintf(fp, "%s", ctx->info[0].my_ip_address.name); fclose(fp); } /* Run external command hook on update. */ if (anychange && ctx->external_command) { os_shell_execute(ctx->external_command, ctx->info[0].my_ip_address.name, ctx->info[0].alias[0].names.name, ctx->bind_interface); } } return rc; }
/** MAIN - Dyn DNS update entry point Actions: - read the configuration options - perform various init actions as specified in the options - create and init dyn_dns object. - launch the IP update action loop */ int dyn_dns_main(ddns_t *ctx, int argc, char *argv[]) { FILE *fp; int rc = 0; int i, s; char name[DYNDNS_SERVER_NAME_LEN]; static int first_startup = 1; if (!ctx) return RC_INVALID_POINTER; /* Create pid and cache file repository. */ mkdir(DYNDNS_RUNTIME_DATA_DIR, 0755); /* read cmd line options and set object properties */ rc = get_config_data(ctx, argc, argv); if (rc != 0 || ctx->abort) return rc; if (ctx->change_persona) { ddns_user_t user; memset(&user, 0, sizeof(user)); user.gid = ctx->sys_usr_info.gid; user.uid = ctx->sys_usr_info.uid; rc = os_change_persona(&user); if (rc != 0) return rc; } /* if logfile provided, redirect output to log file */ if (strlen(ctx->dbg.p_logfilename) != 0) { rc = os_open_dbg_output(DBG_FILE_LOG, "", ctx->dbg.p_logfilename); if (rc != 0) { return rc; } } if (ctx->debug_to_syslog == 1 || (ctx->run_in_background == 1)) { if (get_dbg_dest() == DBG_STD_LOG) { /* avoid file and syslog output */ rc = os_open_dbg_output(DBG_SYS_LOG, "inadyn", NULL); if (rc != 0) { return rc; } } } /* if silent required, close console window */ if (ctx->run_in_background == 1) { rc = close_console_window(); if (rc != 0) { return rc; } if (get_dbg_dest() == DBG_SYS_LOG) { fclose(stdout); } } /* Create files with permissions 0644 */ umask(S_IWGRP | S_IWOTH); /* write pid file */ fp = fopen(ctx->pidfile, "w"); if (!fp) { logit(LOG_ERR, "Failed opening pidfile %s for writing: %s", ctx->pidfile, strerror(errno)); return RC_ERROR; } fprintf(fp, "%u\n", getpid()); fclose(fp); /* "Hello!" Let user know we've started up OK */ logit(LOG_INFO, "%s", DYNDNS_VERSION_STRING); /* On first startup only, optionally wait for network and any NTP daemon * to set system time correctly. Intended for devices without battery * backed real time clocks as initialization of time since last update * requires the correct time. Sleep can be cancelled with any signal, * but it is recommended to use SIGUSR1. */ if (first_startup && ctx->startup_delay_sec) { logit(LOG_NOTICE, "Startup delay: %d sec ...", ctx->startup_delay_sec); os_sleep_ms(1000 * ctx->startup_delay_sec); first_startup = 0; } /* At boot, or when restarting inadyn at runtime, the memory struct holding * our current IP# is empty. We want to avoid unnecessary updates of our * DDNS server record, since we might get locked out for abuse, so we "seed" * each of the DDNS records of our struct with the cached IP# from our cache * file, or from a regular DNS query. */ fp = fopen(ctx->cache_file, "r"); if (!fp) { struct addrinfo hints; struct addrinfo *result; /* Clear DNS cache before querying for the IP below. */ res_init(); /* Try a DNS lookup of our last known IP#. */ for (i = 0; i < ctx->info_count; i++) { if (ctx->info[i].alias_count && /* exception for tunnelbroker.net - no name to lookup */ strcmp(ctx->info[i].system->key, "*****@*****.**")) { /* DNS Lookup */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; /* IPv4 */ hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ hints.ai_flags = 0; hints.ai_protocol = 0; /* Any protocol */ if (!(s = getaddrinfo(ctx->info[i].alias[0].names.name, NULL, &hints, &result))) { /* DNS reply for alias found, convert to IP# */ if (!getnameinfo (result->ai_addr, result->ai_addrlen, name, sizeof(name), NULL, 0, NI_NUMERICHOST)) { /* Update local record for next checkip call. */ strncpy(ctx->info[i].my_ip_address.name, name, sizeof(ctx->info[i].my_ip_address.name)); logit(LOG_INFO, "Resolving hostname %s => IP# %s", ctx->info[i].alias[0].names.name, name); } freeaddrinfo(result); } else { logit(LOG_WARNING, "Failed resolving hostname %s: %s", ctx->info[i].alias[0].names.name, gai_strerror(s)); } } } } else { struct stat statbuf; /* Read cached IP# from inadyn cache file. */ if (fgets(name, sizeof(name), fp)) { logit(LOG_INFO, "Cached IP# %s from previous invocation.", name); /* Update local record for next checkip call. */ for (i = 0; i < ctx->info_count; i++) { strncpy(ctx->info[i].my_ip_address.name, name, sizeof(ctx->info[i].my_ip_address.name)); } } /* Initialize time since last update from modification time of cache file. */ if (fstat(fileno(fp), &statbuf) == 0) { time_t now = time(NULL); if (now != -1 && now > statbuf.st_mtime) { cached_time_since_last_update = (int)(now - statbuf.st_mtime); logit(LOG_INFO, "Cached time since last update %d (seconds) from previous invocation.", cached_time_since_last_update); } } fclose(fp); } do { rc = dyn_dns_init(ctx); if (rc != 0) break; rc = get_encoded_user_passwd(ctx); if (rc != 0) break; if (ctx->update_once == 1) ctx->force_addr_update = 1; /* DDNS client main loop */ while (1) { rc = dyn_dns_update_ip(ctx); if (rc != 0) { if (ctx->cmd == CMD_RESTART) { logit(LOG_INFO, "RESTART command received. Restarting."); rc = RC_RESTART; ctx->cmd = NO_CMD; break; } if (rc == RC_DYNDNS_RSP_NOTOK) { logit(LOG_ERR, "Error response from DDNS server, exiting!"); break; } } else { /* count only the successful iterations */ ctx->num_iterations++; } /* check if the user wants us to stop */ if (ctx->total_iterations != 0 && ctx->num_iterations >= ctx->total_iterations) break; ctx->sleep_sec = rc == RC_DYNDNS_RSP_RETRY_LATER ? ctx->error_update_period_sec : ctx->normal_update_period_sec; if (rc != 0) { /* dyn_dns_update_ip() failed above, and we've not reached MAX iterations. * Time to inform the user the (network) error is not fatal and that we * will try again in a short while. */ logit(LOG_WARNING, "Will retry again in %d sec...", ctx->sleep_sec); } /* Now sleep a while. Using the time set in sleep_sec data member */ dyn_dns_wait_for_cmd(ctx); if (ctx->cmd == CMD_STOP) { logit(LOG_INFO, "STOP command received, exiting."); rc = 0; ctx->cmd = NO_CMD; break; } if (ctx->cmd == CMD_RESTART) { logit(LOG_INFO, "RESTART command received, restarting."); rc = RC_RESTART; ctx->cmd = NO_CMD; break; } if (ctx->cmd == CMD_FORCED_UPDATE) { logit(LOG_INFO, "FORCED_UPDATE command received, updating now."); ctx->force_addr_update = 1; ctx->cmd = NO_CMD; continue; } if (ctx->dbg.level > 0) { logit(LOG_DEBUG, "."); // logit(LOG_DEBUG, "Time since last update: %d", ctx->time_since_last_update); } ctx->time_since_last_update += ctx->sleep_sec; } /* Save old value, if restarted by SIGHUP */ cached_time_since_last_update = ctx->time_since_last_update; cached_num_iterations = ctx->num_iterations; } while (0); /* if everything ok here we should exit. End of program */ if (rc == 0) rc = dyn_dns_shutdown(ctx); return rc; }
static enum data_ret write_data(struct rtmp_stream *stream, bool *can_write, uint64_t *last_send_time, size_t latency_packet_size, int delay_time) { bool exit_loop = false; pthread_mutex_lock(&stream->write_buf_mutex); if (!stream->write_buf_len) { /* this is now an expected occasional condition due to use of * auto-reset events, we could end up emptying the buffer as * it's filled in a previous loop cycle, especially if using * low latency mode. */ pthread_mutex_unlock(&stream->write_buf_mutex); /* blog(LOG_DEBUG, "socket_thread_windows: Trying to send, " "but no data available"); */ return RET_BREAK; } int ret; if (stream->low_latency_mode) { size_t send_len = min(latency_packet_size, stream->write_buf_len); ret = send(stream->rtmp.m_sb.sb_socket, (const char *)stream->write_buf, (int)send_len, 0); } else { ret = send(stream->rtmp.m_sb.sb_socket, (const char *)stream->write_buf, (int)stream->write_buf_len, 0); } if (ret > 0) { if (stream->write_buf_len - ret) memmove(stream->write_buf, stream->write_buf + ret, stream->write_buf_len - ret); stream->write_buf_len -= ret; *last_send_time = os_gettime_ns() / 1000000; os_event_signal(stream->buffer_space_available_event); } else { int err_code; bool fatal_err = false; if (ret == -1) { err_code = WSAGetLastError(); if (err_code == WSAEWOULDBLOCK) { *can_write = false; pthread_mutex_unlock(&stream->write_buf_mutex); return RET_BREAK; } fatal_err = true; } else if (ret == 0) { err_code = 0; fatal_err = true; } if (fatal_err) { /* connection closed, or connection was aborted / * socket closed / etc, that's a fatal error. */ blog(LOG_ERROR, "socket_thread_windows: " "Socket error, send() returned %d, " "GetLastError() %d", ret, err_code); pthread_mutex_unlock(&stream->write_buf_mutex); fatal_sock_shutdown(stream); return RET_FATAL; } } /* finish writing for now */ if (stream->write_buf_len <= 1000) exit_loop = true; pthread_mutex_unlock(&stream->write_buf_mutex); if (delay_time) os_sleep_ms(delay_time); return exit_loop ? RET_BREAK : RET_CONTINUE; }