📄 command.c
字号:
boolcmd_avstream(struct listen_data *listen_data, FILE *client, int argc, char *argv[]){ struct carousel *car = listen_data->carousel; int audio_tag; int video_tag; uint16_t audio_pid; uint16_t video_pid; uint8_t audio_type; uint8_t video_type; int audio_fd; int video_fd; int ts_fd; char hdr[64]; CHECK_USAGE(3, "avstream <AudioTag> <VideoTag>"); audio_tag = strtol(argv[1], NULL, 0); video_tag = strtol(argv[2], NULL, 0); /* map the tags to PIDs and stream types, or use the defaults */ if(audio_tag == -1) { /* check we have a default stream */ if(car->audio_pid == 0) { SEND_RESPONSE(500, "Unable to find audio PID"); return false; } audio_pid = car->audio_pid; audio_type = car->audio_type; } else { audio_pid = stream2pid(&car->assoc, audio_tag); audio_type = stream2type(&car->assoc, audio_tag); } if(video_tag == -1) { /* check we have a default stream */ if(car->video_pid == 0) { SEND_RESPONSE(500, "Unable to find video PID"); return false; } video_pid = car->video_pid; video_type = car->video_type; } else { video_pid = stream2pid(&car->assoc, video_tag); video_type = stream2type(&car->assoc, video_tag); } /* add the PIDs to the demux device */ if((audio_fd = add_demux_filter(car->demux_device, audio_pid, DMX_PES_AUDIO)) < 0) { SEND_RESPONSE(500, "Unable to open audio PID"); return false; } if((video_fd = add_demux_filter(car->demux_device, video_pid, DMX_PES_VIDEO)) < 0) { SEND_RESPONSE(500, "Unable to open video PID"); close(audio_fd); return false; } /* we can now read a transport stream from the dvr device */ if((ts_fd = open(car->dvr_device, O_RDONLY)) < 0) { SEND_RESPONSE(500, "Unable to open DVB device"); close(audio_fd); close(video_fd); return false; } /* send the OK code */ SEND_RESPONSE(200, "OK"); /* tell the client what PIDs and stream types the component tags resolved to */ snprintf(hdr, sizeof(hdr), "AudioPID %u AudioType %u VideoPID %u VideoType %u\n", audio_pid, audio_type, video_pid, video_type); fputs(hdr, client); /* shovel the transport stream down client_sock until the client closes it or we get an error */ stream_ts(ts_fd, client); /* clean up */ close(ts_fd); close(audio_fd); close(video_fd); /* close the connection */ return true;}/* * check <ContentReference> * check if the given file is on the carousel * ContentReference should be absolute, ie start with "~//" */boolcmd_check(struct listen_data *listen_data, FILE *client, int argc, char *argv[]){ char *filename; FILE *file; CHECK_USAGE(2, "check <ContentReference>"); if((filename = external_filename(listen_data, argv[1])) == NULL) { SEND_RESPONSE(500, "Invalid ContentReference"); return false; } if((file = fopen(filename, "r")) != NULL) { fclose(file); SEND_RESPONSE(200, "OK"); } else { SEND_RESPONSE(404, "Not found"); } return false;}/* * file <ContentReference> * send the given file down client_sock * ContentReference should be absolute, ie start with "~//" */boolcmd_file(struct listen_data *listen_data, FILE *client, int argc, char *argv[]){ char *filename; FILE *file; long size; char hdr[64]; long left; size_t nread; char buff[1024 * 8]; CHECK_USAGE(2, "file <ContentReference>"); if((filename = external_filename(listen_data, argv[1])) == NULL) { SEND_RESPONSE(500, "Invalid ContentReference"); return false; } if((file = fopen(filename, "r")) == NULL) { SEND_RESPONSE(404, "Not found"); return false; } /* find the file length */ if(fseek(file, 0, SEEK_END) < 0 || (size = ftell(file)) < 0) { SEND_RESPONSE(500, "Error reading file"); return false; } rewind(file); SEND_RESPONSE(200, "OK"); /* send the file length */ snprintf(hdr, sizeof(hdr), "Length %ld\n", size); fputs(hdr, client); /* send the file contents */ left = size; while(left > 0) { nread = fread(buff, 1, sizeof(buff), file); fwrite(buff, 1, nread, client); left -= nread; } fclose(file); return false;}/* * help */boolcmd_help(struct listen_data *listen_data, FILE *client, int argc, char *argv[]){ int i; char name_args[64]; char help_line[128]; SEND_RESPONSE(200, "OK"); for(i=0; command[i].name != NULL; i++) { snprintf(name_args, sizeof(name_args), "%s %s", command[i].name, command[i].args); snprintf(help_line, sizeof(help_line), "%-30s %s\n", name_args, command[i].help); fputs(help_line, client); } return false;}/* * quit */boolcmd_quit(struct listen_data *listen_data, FILE *client, int argc, char *argv[]){ return true;}/* * return a filename that can be used to load the given ContentReference from the filesystem * returns a static string that will be overwritten by the next call to this routine * returns NULL if the ContentReference is invalid (does not start with ~// or has too many .. components) */static char _external[PATH_MAX];char *external_filename(struct listen_data *listen_data, char *cref){ char *canon_cref; /* is ContentReference absolute */ if(strlen(cref) < 3 || strncmp(cref, "~//", 3) != 0) return NULL; /* strip off the ~// prefix, and canonicalise the reference */ canon_cref = canonical_filename(cref + 3); /* if the canonical name starts with "../", it is invalid */ if(strcmp(canon_cref, "..") == 0 || strncmp(canon_cref, "../", 3) == 0) return NULL; /* create the carousel filename, ie prepend the servive gateway directory */ snprintf(_external, sizeof(_external), "%s/%u/%s", SERVICES_DIR, listen_data->carousel->service_id, canon_cref); return _external;}/* * return a string that recursively removes all sequences of the form '/x/../' in path * returns a static string that will be overwritten by the next call to this routine */static char _canon[PATH_MAX];char *canonical_filename(char *path){ char *start; char *slash; size_t len; /* copy path into the output buffer */ strncpy(_canon, path, sizeof(_canon)); /* just in case */ _canon[sizeof(_canon)-1] = '\0'; /* keep removing "/x/../" until there are none left */ start = _canon; while(true) { /* find the start of the first path component that is not "../" */ while(strncmp(start, "../", 3) == 0) start += 3; /* find the next slash in the path */ slash = start; while(*slash != '/' && *slash != '\0') slash ++; /* no more slashes => nothing left to do */ if(*slash == '\0') return _canon; /* if this component is empty (ie ./ or /) remove it */ if(strncmp(start, "./", 2) == 0 || *start == '/') { /* include \0 terminator */ len = strlen(slash + 1) + 1; memmove(start, slash + 1, len); /* restart the search */ start = _canon; } /* if the next path component is "../", eat this one */ else if(strncmp(slash, "/../", 4) == 0) { /* include \0 terminator */ len = strlen(slash + 4) + 1; memmove(start, slash + 4, len); /* restart the search */ start = _canon; } else { /* move to the next component */ start = slash + 1; } } /* not reached */ return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -