static int get_socket (struct sockaddr *sa, socklen_t socklen_in, int domain) { int s; const int one = 1; int bind_rc, rc_ok = 0; errno = 0; s = socket(domain, SOCK_DGRAM, IPPROTO_UDP); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); if (s != -1) { errno = 0; bind_rc = bind(s, sa, socklen_in); if (!bind_rc) { rc_ok = 1; } else { trace_warn("Cannot bind to indexnode listener socket: %s\n", strerror(errno)); } } else { trace_warn("Cannot create indexnode listener socket: %s\n", strerror(errno)); } return rc_ok ? s : -1; }
static void print_network_interfaces (void) { struct ifaddrs *ifaddr, *ifa; int family, s; /* TODO: make this a config option */ trace_info("Listening on all addresses:\n"); errno = 0; if (getifaddrs(&ifaddr) == -1) { trace_warn("Cannot get interface addresses: %s\n", strerror(errno)); } for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) { char host[NI_MAXHOST]; family = ifa->ifa_addr->sa_family; /* For an AF_INET* interface address, display the address, interface and * address family */ if (family == AF_INET || family == AF_INET6) { s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST ); if (s) { trace_warn("Cannot getnameinfo(): %s\n", gai_strerror(s)); } trace_info("\t%s (%s, %s)\n", host, ifa->ifa_name, (family == AF_INET) ? "AF_INET" : (family == AF_INET6) ? "AF_INET6" : "" ); } } trace_info("\n"); freeifaddrs(ifaddr); }
static void *alarm_thread_main( void *ctxt ) { alarm_t *alarm = (alarm_t *)ctxt; struct timeval tv; fd_set r_fds; int exiting = 0; int select_rc; alarm_control_codes_t msg = alarm_control_codes_NOT_USED; FD_ZERO(&r_fds); while( !exiting ) { FD_SET( alarm->pipe_read, &r_fds ); /* man 2 select: "consider tv undefined after select returns */ bzero( &tv, sizeof(tv) ); tv.tv_sec = alarm->interval; /* TODO: pselect */ errno = 0; select_rc = select( alarm->pipe_read + 1, &r_fds, NULL, NULL, &tv ); switch( select_rc ) { case -1: trace_warn("Error waiting for alarm timeout / control signal: %s\n", strerror(errno)); break; case 0: /* No fds active == timeout */ alarm->cb( alarm->cb_data ); break; case 1: if( FD_ISSET(alarm->pipe_read, &r_fds) ) { assert( read( alarm->pipe_read, &msg, sizeof(msg) ) == sizeof(msg) ); assert( msg == alarm_control_codes_STOP ); exiting = 1; } else { assert( 0 ); } break; default: assert( 0 ); } } return NULL; }
static void listener_thread_event_loop (int s4, int s6, int control_fd, new_indexnode_event_t packet_received_cb, void *packet_received_ctxt) { fd_set r_fds; int select_rc; int exiting = 0; listener_control_codes_t msg = listener_control_codes_NOT_USED; FD_ZERO(&r_fds); assert(control_fd != -1); while (!exiting) { if (s4 != -1) FD_SET(s4, &r_fds); if (s6 != -1) FD_SET(s6, &r_fds); FD_SET(control_fd, &r_fds); errno = 0; /* TODO: use pselect to block all signals to this thread so select * doesn't wake randomly. Assert no EAGAIN (shouldn't see it). */ select_rc = select(MAX(s4, MAX(s6, control_fd)) + 1, &r_fds, NULL, NULL, NULL); switch (select_rc) { case -1: trace_warn("Error waiting for indexnode broadcast: %s\n", strerror(errno)); break; case 0: /* No fds active == timeout */ assert(0); break; default: if ((s4 != -1) && FD_ISSET(s4, &r_fds)) { struct sockaddr_in sa; receive_advert(s4, (struct sockaddr *)&sa, sizeof(sa), &(sa.sin_addr), INET_ADDRSTRLEN, packet_received_cb, packet_received_ctxt); } if ((s6 != -1) && FD_ISSET(s6, &r_fds)) { struct sockaddr_in6 sa; receive_advert(s6, (struct sockaddr *)&sa, sizeof(sa), &(sa.sin6_addr), INET6_ADDRSTRLEN, packet_received_cb, packet_received_ctxt); } if (FD_ISSET(control_fd, &r_fds)) { assert(read(control_fd, &msg, sizeof(msg)) == sizeof(msg)); assert(msg == listener_control_codes_STOP); exiting = 1; } break; } } }
static void receive_advert( const int socket, struct sockaddr *sa, const socklen_t socklen_in, void * const addr_src, const size_t host_len, new_indexnode_event_t packet_received_cb, void *packet_received_ctxt ) { char host[host_len]; char buf[1024]; char *port, *fs2protocol, *id; string_buffer_t *buffer = string_buffer_new(); int recv_rc; socklen_t socklen; /* For UDP it is specified that recv*() will return the whole packet in one * go. It is not correct to keep calling recv*() to get more of the message; * this isn't a stream. If the message is too big for the buffer it's simply * truncated. Usually silently, but by passing in MSG_TRUNC one gets the * real length of the message back, even if it has to be truncated. This * allows us to assert that our buffer is big enough. We've had to take a * guess because advert packets are variable length, but it's an assertion * because 1024 really should be enough */ errno = 0; recv_rc = recvfrom(socket, buf, sizeof(buf) - 1, MSG_TRUNC, sa, &socklen); assert(recv_rc <= (int)sizeof(buf) - 1); if (recv_rc >= 0) { assert(socklen == socklen_in); buf[recv_rc] = '\0'; string_buffer_append(buffer, strdup(buf)); if (!parse_advert_packet(string_buffer_peek(buffer), &port, &fs2protocol, &id) && inet_ntop(AF_INET, addr_src, host, sizeof(host) - 1)) { packet_received_cb(packet_received_ctxt, strdup(host), port, fs2protocol, id); } } else { trace_warn("failed to recvfrom() and indexnode advert packet: %s\n", strerror(errno)); } string_buffer_delete(buffer); }
int pid_map_table_apply(struct xmux_pid_map_table *pid_map_data) { int size = sizeof(struct xmux_pid_map_table); if (size > sizeof(tmp_pid_map.pid_map)) { trace_warn("pid map table struct exceed! check it!"); return -1; } tmp_pid_map.cha = CHANNEL_ALL_BITMAP; memcpy((unsigned char *)&tmp_pid_map.pid_map, pid_map_data, sizeof(*pid_map_data)); hfpga_write_pid_map(&tmp_pid_map); return 0; }
void manage_add_chair(struct device *d) { int i; for( i=0 ; i<array_size(chairs) ; i++ ) { if( chairs[i] == d ) { /* already added */ return; } else if( !chairs[i] ) { chairs[i] = d; return; } } /* we should not get here.. */ trace_warn("too many chair devices."); }
struct fp_cmd * front_panel_send_cmd(struct fp_cmd *cmd, int expect_cmd) { int rc; struct fp_cmd *resp_cmd = NULL; if (wu_swait_is_alive(&fp_swait)) { trace_warn("busy! ignore this send cmd request!"); return NULL; } rc = write(fd, cmd, FP_CMD_SIZE(cmd)); if (rc < FP_CMD_SIZE(cmd)) { trace_err("wirte cmd failed!"); return NULL; } fp_expect_cmd = expect_cmd; resp_cmd = wu_swait_timedwait(&fp_swait, 2000000); fp_expect_cmd = -1; return resp_cmd; }
/* * @return: 1 the @cmd is response cmd */ int front_panel_check_recv_cmd(struct fp_cmd *recv_cmd) { int cmd = SWAP_U16(recv_cmd->header.seq) & 0x7FFF; int is_read = SWAP_U16(recv_cmd->header.seq) & 0x8000; bool check_enter_fp = true; /* * check force enter to fp management mode */ if (cmd == FP_CMD_SYS) { uint16_t sys_cmd = READ_U16_BE(recv_cmd->data); if (sys_cmd == FP_SYS_CMD_READ_TS_STATUS || sys_cmd == FP_SYS_CMD_ENTER_FP_MANAGEMENT_MODE || sys_cmd == FP_SYS_CMD_LEAVE_FP_MANAGEMENT_MODE) { check_enter_fp = false; } } else if (cmd == FP_CMD_OUT_RATE && is_read) { check_enter_fp = false; } if (check_enter_fp && (management_mode != MANAGEMENT_MODE_FP)) { trace_warn("recv cmd in none fp mode! force switch!"); enter_fp_management_mode(); } if (cmd == fp_expect_cmd) { static char buf[1024]; struct fp_cmd *resp_cmd = (struct fp_cmd *)buf; fp_cmd_copy(resp_cmd, recv_cmd); if (wu_swait_wakeup(&fp_swait, resp_cmd)) { trace_err("recv respone cmd %d, but maybe had timeouted!", cmd); } return 1; } return 0; }
static int do_parse_channel(PROG_INFO_T *chan_prog_info, uint8_t * p_chan_prog_cnt, uint8_t chan_idx) { int i, j, k; uint8_t prog_cnt = 0; PROG_INFO_T *prog_info; int rc = 0; uint16_t pids[PROGRAM_PID_MAX_NUM]; int nr_pids; pmt.p_descr = pmt_descr; for (i = 0; i < 5; i++) { pmt_descr[i].p_data = p_pmt_data[i]; } for (i = 0; i < PROGRAM_MAX_NUM; i++) { es[i].p_descr = es_descr[i]; stream[i].p_descr = stream_descr[i]; serv[i].p_descr = serv_descr[i]; for (j = 0; j < 5; j++) { es_descr[i][j].p_data = p_es_data[i][j]; stream_descr[i][j].p_data = p_stream_data[i][j]; serv_descr[i][j].p_data = p_serv_data[i][j]; } } hfpga_dev.cha = chan_idx; dvbSI_Start(&hfpga_dev); trace_info("decode PAT ..."); sg_si_param.tbl_type = EUV_TBL_PAT; psi_parse_timer_start(5); rc = dvbSI_Dec_PAT(&pat, pid_data, &pid_num); psi_parse_timer_stop(); if (rc) { trace_err("pat parse failed! rc %d\n", rc); goto channel_analyse_done; } trace_info("PAT decode done, TS id %#x, pmt pid num %d", pat.i_tran_stream_id, pid_num); for (i = 0; i < pid_num; i++) { trace_info(" program #%d: program number %#x, PMT %#x", i, pid_data[i].i_pg_num, pid_data[i].i_pid); } trace_info("decode PMT ..."); #if CHANNEL_MAX_NUM == 1 sg_si_param.type = EUV_BOTH; #endif sg_si_param.tbl_type = EUV_TBL_PMT; for (i = 0; i < pid_num; i++) { if (pid_data[i].i_pg_num != 0x00) { prog_info = chan_prog_info + prog_cnt; prog_cnt++; prog_info->info.pmt.in = pid_data[i].i_pid; prog_info->info.pmt.out = pid_map_rule_map_psi_pid(chan_idx, prog_cnt - 1, DSW_PID_PMT, pid_data[i].i_pid, NULL, 0); prog_info->info.prog_num = pid_data[i].i_pg_num; trace_info("decode program_number %d, PMT %#x ...", pid_data[i].i_pg_num, pid_data[i].i_pid); pmt.i_pg_num = pid_data[i].i_pg_num; pmt.i_pmt_pid = pid_data[i].i_pid; #if CHANNEL_MAX_NUM == 1 memset(g_input_pmt_sec[prog_cnt - 1], 0, 2); sg_si_param.cur_cnt = 0; sg_si_param.sec[0] = g_input_pmt_sec[prog_cnt - 1]; #endif psi_parse_timer_start(5); rc = dvbSI_Dec_PMT(&pmt, es, &es_num); psi_parse_timer_stop(); if (rc) { trace_err("pmt parse #%d failed! rc %d\n", i, rc); goto channel_analyse_done; } #if CHANNEL_MAX_NUM == 1 /* * pmt descriptors * if we found CA_Descriptor, then it's scrambled! */ for (j = 0; j < pmt.i_descr_num; j++) { trace_info("PMT desc #%d, tag %#x, len %d, data:", j, pmt.p_descr[j].i_tag, pmt.p_descr[j].i_length); if (pmt.p_descr[j].i_tag == CA_DR_TAG) { trace_info("found CA_Descriptor!"); prog_info->status |= FP_STATUS_SCRAMBLED; } } #endif /* * clip max es number */ if (es_num > PROGRAM_DATA_PID_MAX_NUM) es_num = PROGRAM_DATA_PID_MAX_NUM; /* * scan PCR and data PIDs and we'll use them do pid remap */ nr_pids = scan_program_pids(&pmt, &es, es_num, pids); prog_info->info.pcr.type = PID_TYPE_PCR; prog_info->info.pcr.in = pmt.i_pcr_pid; prog_info->info.pcr.out = pid_map_rule_map_psi_pid(chan_idx, prog_cnt - 1, DSW_PID_PCR, pmt.i_pcr_pid, pids, nr_pids); trace_info("PCR %#x, %d descrs", pmt.i_pcr_pid, pmt.i_descr_num); for (j = 0; j < pmt.i_descr_num; j++) { trace_info("desc %d, tag %#x, len %d", j, pmt.p_descr[j].i_tag, pmt.p_descr[j].i_length); hex_dump("desc", pmt.p_descr[j].p_data, pmt.p_descr[j].i_length); } for (j = 0; j < es_num; j++) { trace_info("es %d, type %#x, pid %#x", j, es[j].i_type, es[j].i_pid); prog_info->info.data[j].type = es[j].i_type; if (es[j].i_pid != pmt.i_pcr_pid) { prog_info->info.data[j].in = es[j].i_pid; prog_info->info.data[j].out = pid_map_rule_map_psi_pid(chan_idx, prog_cnt - 1, DSW_PID_VIDEO, es[j].i_pid, pids, nr_pids); } else { prog_info->info.data[j].in = es[j].i_pid; prog_info->info.data[j].out = prog_info->info.pcr.out; /* correct pcr type */ if (es_is_video(es[j].i_type)) prog_info->info.pcr.type = PID_TYPE_PCR_VIDEO; else prog_info->info.pcr.type = PID_TYPE_PCR_AUDIO; } for (k = 0; k < es[j].i_descr_num; k++) { trace_info("es descriptor %d, tag %#x, len %d", k, es[j].p_descr[k].i_tag, es[j].p_descr[k].i_length); hex_dump("desc", es[j].p_descr[k].p_data, es[j].p_descr[k].i_length); } } } } *p_chan_prog_cnt = prog_cnt; trace_info("decode SDT ..."); sg_si_param.type = EUV_DEFAULT; sg_si_param.tbl_type = EUV_TBL_SDT; psi_parse_timer_start(20); rc = parse_sdt_section_and_decode(chan_idx, &sdt, serv, &serv_num); psi_parse_timer_stop(); if (rc) { trace_err("sdt parse failed! rc %d\n", rc); goto channel_analyse_done; } trace_info("there are total %d services", serv_num); for (j = 0; j < serv_num; j++) { for (i = 0; i < prog_cnt; i++) { prog_info = chan_prog_info + i; if (serv[j].i_serv_id == prog_info->info.prog_num) { trace_info("service #%d: service_id %#x", j, serv[j].i_serv_id); extract_program_name(serv[j].p_descr->p_data, (unsigned char *)prog_info->info.prog_name); /* set default output program name same with original */ memcpy(prog_info->info.prog_name[1], prog_info->info.prog_name[0], PROGRAM_NAME_SIZE); break; } } if (i == prog_cnt) { trace_warn("service #%d: service_id %#x, no owner program!", j, serv[j].i_serv_id); } } channel_analyse_done: dvbSI_Stop(); return rc; }
static int cmd_reg(struct cmd *cmd) { int a=0; char *p; struct device *d; struct db_device *dd; char sum[64]; unsigned int n; int type; char *pass; int port; char *bcast; int did = cmd->device_id; char buf[CMD_MAX]; NEXT_ARG(p); type = atoi(p); NEXT_ARG(p); pass = p; NEXT_ARG(p); port = atoi(p); NEXT_ARG(p); bcast = p; /* authenticate the passwd based on id and type */ n = (unsigned int)cmd->device_id ^ (unsigned int)type; cksum(&n, sizeof n, sum); if (strcmp(pass, sum) != 0) { trace_warn("authenticate fail\n"); return 1; } if (port <= 0) return 1; dd = md_find_device(did); if( dd ) { /* mark it online even if it's disabled. * needed for the manager to identify online devs. */ dd->online = 1; if( !dd->enabled ) { return ERR_DEV_DISABLED; } } d = get_device(did); if( !d ) { d = dev_create(did); } d->type = type; d->addr = *cmd->saddr; d->addr.sin_port = htons(port); d->fileaddr = d->addr; d->fileaddr.sin_port = htons(port+1); if (strcmp("none", bcast) == 0) d->bcast.sin_addr.s_addr = 0; else { d->bcast.sin_addr.s_addr = inet_addr(bcast); d->bcast.sin_port = htons(BRCAST_PORT); } dev_update_data(d); if (dev_register(d) != 0) { /* existing dev ok */ } dev_activate(d); if( is_ptc(d) ) { /* re-set ptc if it's restarted. */ ptc_go_current(); } if( d->type == DEVTYPE_CHAIR ) { manage_notify_chair(d); } get_client_info(buf, d); REP_ADD(cmd, "OK"); REP_ADD(cmd, buf); REP_END(cmd); return 0; }