static struct rtsp *start_test_client(void) { int r, fds[2] = { }; r = sd_event_default(&event); ck_assert_int_ge(r, 0); r = socketpair(AF_UNIX, SOCK_STREAM, 0, fds); ck_assert_int_ge(r, 0); ck_assert_int_ge(fds[0], 0); ck_assert_int_ge(fds[1], 0); r = rtsp_open(&server, fds[0]); ck_assert_int_ge(r, 0); r = rtsp_attach_event(server, event, 0); ck_assert_int_ge(r, 0); r = rtsp_open(&client, fds[1]); ck_assert_int_ge(r, 0); r = rtsp_attach_event(client, event, 0); ck_assert_int_ge(r, 0); return client; }
static void sink_connected(struct ctl_sink *s) { int r, val; socklen_t len; if (s->connected || s->hup) return; sd_event_source_set_enabled(s->fd_source, SD_EVENT_OFF); len = sizeof(val); r = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &len); if (r < 0) { s->hup = true; cli_vERRNO(); return; } else if (val) { s->hup = true; errno = val; cli_error("cannot connect to remote host (%d): %m", errno); return; } cli_debug("connection established"); r = rtsp_open(&s->rtsp, s->fd); if (r < 0) goto error; r = rtsp_attach_event(s->rtsp, s->event, 0); if (r < 0) goto error; r = rtsp_add_match(s->rtsp, sink_rtsp_fn, s); if (r < 0) goto error; s->connected = true; ctl_fn_sink_connected(s); return; error: s->hup = true; cli_vERR(r); }
static demuxer_t* demux_open_rtp(demuxer_t* demuxer) { nms_rtsp_hints hints; char * url = demuxer->stream->streaming_ctrl->url->url; rtsp_ctrl * ctl; RTSP_Error reply; rtsp_medium * media; Nemesi_DemuxerStreamData * ndsd = calloc(1, sizeof(Nemesi_DemuxerStreamData)); memset(&hints,0,sizeof(hints)); if (rtsp_port) hints.first_rtp_port = rtsp_port; if (rtsp_transport_tcp) { hints.pref_rtsp_proto = TCP; hints.pref_rtp_proto = TCP; } if (rtsp_transport_sctp) { hints.pref_rtsp_proto = SCTP; hints.pref_rtp_proto = SCTP; } mp_msg(MSGT_DEMUX, MSGL_INFO, "Initializing libNemesi\n"); if ((ctl = rtsp_init(&hints)) == NULL) { free(ndsd); return STREAM_ERROR; } ndsd->rtsp = ctl; demuxer->priv = ndsd; //nms_verbosity_set(1); mp_msg(MSGT_DEMUX, MSGL_INFO, "Opening: %s\n", url); if (rtsp_open(ctl, url)) { mp_msg(MSGT_DEMUX, MSGL_ERR, "rtsp_open failed.\n"); return demuxer; } reply = rtsp_wait(ctl); if (reply.got_error) { mp_msg(MSGT_DEMUX, MSGL_ERR, "OPEN Error from the server: %s\n", reply.message.reply_str); return demuxer; } rtsp_play(ctl, 0, 0); reply = rtsp_wait(ctl); if (reply.got_error) { mp_msg(MSGT_DEMUX, MSGL_ERR, "PLAY Error from the server: %s\n", reply.message.reply_str); return demuxer; } if (!ctl->rtsp_queue) return demuxer; media = ctl->rtsp_queue->media_queue; for (; media; media=media->next) { sdp_medium_info * info = media->medium_info; rtp_session * sess = media->rtp_sess; rtp_buff buff; int media_format = atoi(info->fmts); rtp_pt * ptinfo = rtp_get_pt_info(sess, media_format); char const * format_name = ptinfo ? ptinfo->name : NULL; memset(&buff, 0, sizeof(rtp_buff)); if (sess->parsers[media_format] == NULL) { mp_msg(MSGT_DEMUX, MSGL_ERR, "libNemesi unsupported media format: %s\n", format_name ? format_name : info->fmts); continue; } else { mp_msg(MSGT_DEMUX, MSGL_INFO, "libNemesi supported media: %s\n", format_name); } if (ptinfo->type == AU) { if (ndsd->session[NEMESI_SESSION_AUDIO] == NULL) { sh_audio_t* sh_audio = new_sh_audio(demuxer,0, NULL); WAVEFORMATEX* wf; demux_stream_t* d_audio = demuxer->audio; demuxer->audio->id = 0; mp_msg(MSGT_DEMUX, MSGL_INFO, "Detected as AUDIO stream...\n"); link_session_and_fetch_conf(ndsd, NEMESI_SESSION_AUDIO, sess, &buff, NULL); wf = calloc(1,sizeof(*wf)+buff.len); wf->cbSize = buff.len; memcpy(wf+1, buff.data, buff.len); sh_audio->wf = wf; d_audio->sh = sh_audio; wf->nSamplesPerSec = 0; wf->wFormatTag = sh_audio->format = get4CC(supported_audio, format_name); if ( !(wf->wFormatTag) ) mp_msg(MSGT_DEMUX, MSGL_WARN, "Unknown MPlayer format code for MIME" " type \"audio/%s\"\n", format_name); } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "There is already an audio session registered," " ignoring...\n"); } } else if (ptinfo->type == VI) { if (ndsd->session[NEMESI_SESSION_VIDEO] == NULL) { sh_video_t* sh_video; BITMAPINFOHEADER* bih; demux_stream_t* d_video; int fps = 0; mp_msg(MSGT_DEMUX, MSGL_INFO, "Detected as VIDEO stream...\n"); link_session_and_fetch_conf(ndsd, NEMESI_SESSION_VIDEO, sess, &buff, &fps); bih = calloc(1,sizeof(*bih)+buff.len); bih->biSize = sizeof(*bih)+buff.len; memcpy(bih+1, buff.data, buff.len); sh_video = new_sh_video(demuxer,0); sh_video->bih = bih; d_video = demuxer->video; d_video->sh = sh_video; if (fps) { sh_video->fps = fps; sh_video->frametime = 1.0/fps; } bih->biCompression = sh_video->format = get4CC(supported_video, format_name); if ( !(bih->biCompression) ) { mp_msg(MSGT_DEMUX, MSGL_WARN, "Unknown MPlayer format code for MIME" " type \"video/%s\"\n", format_name); } } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "There is already a video session registered," " ignoring...\n"); } } else { mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported media type\n"); } } demuxer->stream->eof = 0; return demuxer; }
TEST_END_CASE START_TEST(msg_new_invalid) { char data[128] = { }; struct rtsp *bus; struct rtsp_message *m; int r, fd; fd = dup(0); ck_assert_int_ge(fd, 0); r = rtsp_open(&bus, fd); ck_assert_int_ge(r, 0); /* request messages */ m = TEST_INVALID_PTR; r = rtsp_message_new_request(NULL, &m, "method", "uri"); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_request(bus, NULL, "method", "uri"); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_request(bus, &m, "", "uri"); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_request(bus, &m, NULL, "uri"); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_request(bus, &m, "method", ""); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_request(bus, &m, "method", NULL); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_request(bus, &m, "method", "uri"); ck_assert_int_ge(r, 0); ck_assert(m != TEST_INVALID_PTR); rtsp_message_unref(m); /* reply-for messages */ m = TEST_INVALID_PTR; r = rtsp_message_new_reply(NULL, &m, 1, 200, "OK"); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_reply(bus, NULL, 1, 200, "OK"); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_reply(bus, &m, 0, 200, "OK"); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_reply(bus, &m, 1, RTSP_ANY_CODE, "OK"); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_reply(bus, &m, 1, 200, "OK"); ck_assert_int_ge(r, 0); ck_assert(m != TEST_INVALID_PTR); rtsp_message_unref(m); /* data messages */ m = TEST_INVALID_PTR; r = rtsp_message_new_data(NULL, &m, 0, data, sizeof(data)); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_data(bus, NULL, 0, data, sizeof(data)); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_data(bus, &m, RTSP_ANY_CHANNEL, data, sizeof(data)); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_data(bus, &m, 0, NULL, sizeof(data)); ck_assert_int_lt(r, 0); ck_assert(m == TEST_INVALID_PTR); r = rtsp_message_new_data(bus, &m, 0, data, sizeof(data)); ck_assert_int_ge(r, 0); ck_assert(m != TEST_INVALID_PTR); rtsp_message_unref(m); /* invalid ops */ rtsp_message_ref(NULL); rtsp_message_unref(NULL); ck_assert_int_eq(rtsp_message_get_type(NULL), 0); ck_assert(!rtsp_message_get_method(NULL)); ck_assert(!rtsp_message_get_uri(NULL)); ck_assert_int_eq(rtsp_message_get_code(NULL), RTSP_ANY_CODE); ck_assert(!rtsp_message_get_phrase(NULL)); ck_assert_int_eq(rtsp_message_get_channel(NULL), RTSP_ANY_CHANNEL); ck_assert(!rtsp_message_get_payload(NULL)); ck_assert_int_eq(rtsp_message_get_payload_size(NULL), 0); ck_assert(!rtsp_message_is_request(NULL, NULL, NULL)); ck_assert(!rtsp_message_is_reply(NULL, RTSP_ANY_CODE, NULL)); ck_assert(!rtsp_message_is_data(NULL, RTSP_ANY_CHANNEL)); ck_assert(!rtsp_message_get_bus(NULL)); ck_assert(!rtsp_message_get_cookie(NULL)); ck_assert(!rtsp_message_is_sealed(NULL)); rtsp_unref(bus); }
int main(int argc, char **argv) { int opt; char *url, *out = "nemesi.dump"; FILE *outfile = NULL; rtsp_ctrl *ctl; rtsp_session *sess; rtsp_medium *med; nms_rtsp_hints rtsp_hints = { -1 }; sdp_attr *attr; RTSP_Error reply; if (argc < 2) { fprintf(stderr, "\tPlease specify at least an url.\n"); fprintf(stderr, "\tUsage: %s [-f outputfile ] [-p rtp_port] [-t url\n", argv[0]); exit(1); } #ifndef WIN32 while ((opt = getopt(argc, argv, "df:p:v:")) != -1) { switch (opt) { /* Set output file */ case 'f': out = strdup(optarg); break; /* Set rtp port */ case 'p': rtsp_hints.first_rtp_port = atoi(optarg); break; /* Set verbosity */ case 'v': nms_verbosity_set(atoi(optarg)); break; /* Unknown option */ case '?': fprintf(stderr, "\n Unknown option `-%c'.\n", optopt); fprintf(stderr, "\tUsage: %s [-f outputfile ] [-d] url\n\n", argv[0]); return 1; } } #endif outfile = fopen(out, "rb"); if (outfile == NULL) outfile = stderr; url = argv[argc - 1]; fprintf(stderr, "URL %s.\n", url); /* initialize the rtsp state machine, starts the rtsp and the rtp threads * the hints available are just one: * - the first port to use (instead of picking one at random) */ if ((ctl = rtsp_init(&rtsp_hints)) == NULL) { fprintf(stderr, "Cannot init rtsp.\n"); return 1; } if (rtsp_open(ctl, url)) { fprintf(stderr, "rtsp_open failed.\n"); // die return 1; } // you must call rtsp_wait after issuing any command reply = rtsp_wait(ctl); printf("OPEN: Received reply from server: %s\n", reply.message.reply_str); // Get the session information sess = ctl->rtsp_queue; if (!sess) { fprintf(stderr, "No session available.\n"); return 1; } while (sess) { // foreach session... fprintf(outfile, "\tSession %s\n", sess->pathname); fprintf(outfile, "\tSession Duration %s\n", sess->info->t); for (attr = sess->info->attr_list; attr; attr = attr->next) { fprintf(outfile, "\t* %s %s\n", attr->name, attr->value); } med = sess->media_queue; while (med) { //... foreach medium switch (med->medium_info->media_type) { // Just care about audio and video case 'A': case 'V': fprintf(outfile, "\tTransport %s\n", med->medium_info->transport); fprintf(outfile, "\tMedia Type %s\n", (med->medium_info->media_type == 'A'? "Audio" : "Video")); fprintf(outfile, "\tMedia format %s\n", med->medium_info->fmts); break; default: //do nothing break; } // attributes are already parsed, get them from the list for (attr = med->medium_info->attr_list; attr; attr = attr->next) { fprintf(outfile, "\t* %s %s\n", attr->name, attr->value); } med = med->next; } sess = sess->next; } /* * Close the rtsp connection, we are polite */ rtsp_close(ctl); reply = rtsp_wait(ctl); printf("CLOSE: Received reply from server: %s\n", reply.message.reply_str); /* * Kill the threads, dealloc everything. */ rtsp_uninit(ctl); return 0; }
/** * @brief scan status code of an RTSP reply * * @param status_line the status line in the reply * @return reply status code or -1 on error */ int check_status(char *status_line, rtsp_thread * rtsp_th) { char ver[32]; unsigned short res_state; char *reason_phrase; char *location = NULL; // string tokenizers char *tkn, *prev_tkn, *step = NULL; if (sscanf(status_line, "%31s %hu ", ver, &res_state) < 2) { nms_printf(NMSML_ERR, "invalid Status-Line in DESCRIBE Response\n"); return -1; } reason_phrase = strchr(strchr(status_line, ' ') + 1, ' ') + 1; rtsp_th->response_id = res_state; if (RTSP_IS_SUCCESS(res_state)) return res_state; else if (RTSP_IS_REDIRECT(res_state)) { nms_printf(NMSML_NORM, "WARNING: Redirection. reply was: %hu %s\n", res_state, reason_phrase); switch (res_state) { case RTSP_FOUND: if ((prev_tkn = strtok_r(rtsp_th->in_buffer.data + strlen(status_line) + 1, "\n", &step)) == NULL) { nms_printf(NMSML_ERR, "Could not find \"Location\" so..." " Where I'll redirect you?\n"); return -1; } while (((tkn = strtok_r(NULL, "\n", &step)) != NULL) && ((tkn - prev_tkn) > 1)) { if (((tkn - prev_tkn) == 2) && (*prev_tkn == '\r')) break; if (!strncasecmp(prev_tkn, "Location", 8)) { prev_tkn += 8; while ((*(prev_tkn) == ' ') || (*(prev_tkn) == ':')) prev_tkn++; location = strdup(prev_tkn); // sscanf(prev_tkn,"%d",&location); } prev_tkn = tkn; } if (location) { nms_printf(NMSML_NORM, "Redirecting to %s\n", location); rtsp_open((rtsp_ctrl*)rtsp_th, location); } else return -nms_printf(NMSML_ERR, "No location string\n"); } } else if (RTSP_IS_CLIENT_ERROR(res_state)) nms_printf(NMSML_ERR, "Client error. Reply was: %hu %s\n", res_state, reason_phrase); else if (RTSP_IS_SERVER_ERROR(res_state)) nms_printf(NMSML_ERR, "Server error. Reply was: %hu %s\n", res_state, reason_phrase); return -1; }