static utility_retcode_t parse_one_header(struct rtsp_response *response) { utility_retcode_t ret = UTILITY_SUCCESS; char *start_value; char *header_name = response->current_header.name; char *header_value = response->current_header.value; FUNC_ENTER; ret = utility_copy_token(header_name, MAX_HEADER_NAME_LEN, response->parsep, ": ", NULL); if (UTILITY_SUCCESS != ret) { ERRR("Failed to copy header name\n"); goto out; } start_value = begin_token(response->parsep, ": "); ret = utility_copy_token(header_value, MAX_HEADER_VALUE_LEN, start_value, "\r\n", NULL); if (UTILITY_SUCCESS != ret) { ERRR("Failed to copy header value\n"); goto out; } DEBG("Found header name: \"%s\" value: \"%s\"\n", header_name, header_value); if (0 == syscalls_strcmp(header_name, "Content-Length")) { ret = parse_content_length(response); } else if (0 == syscalls_strcmp(header_name, "Apple-Response")) { ret = parse_apple_response(response); } else if (0 == syscalls_strcmp(header_name, "Audio-Jack-Status")) { ret = parse_audio_jack_status(response); } else if (0 == syscalls_strcmp(header_name, "Session")) { ret = parse_session(response); } else if (0 == syscalls_strcmp(header_name, "Transport")) { ret = parse_transport(response); } else if (0 == syscalls_strcmp(header_name, "Public")) { ret = parse_public(response); } else { parse_unknown_header(response); } out: FUNC_RETURN; return ret; }
Errcode Parser::parse_field(const Line& line) { Fields::const_iterator field = _fields.find(_words[line.word]); // we ignore fields we don't understand if (field == _fields.end()) return OK; // verify that Field does have argument if (line.count == 0) return ERROR_MISSING_FIELD_ARG; char* arg = _words[line.word + 1]; switch (field->second) { case CSeq: data.cseq = strtol(arg, 0, 0); break; case Accept: data.accept = arg; break; case _Transport: parse_transport(line); break; case Session: data.session_id = arg; break; } return OK; }
static enum rtsp_result rtsp_handle(access_t *access, bool *interrupted) { access_sys_t *sys = access->p_sys; uint8_t buffer[512]; int rtsp_result = 0; bool have_header = false; size_t content_length = 0; size_t read = 0; char *in, *val; /* Parse header */ while (!have_header) { in = net_readln_timeout((vlc_object_t*)access, sys->tcp_sock, 5000, interrupted); if (in == NULL) break; if (strncmp(in, "RTSP/1.0 ", 9) == 0) { rtsp_result = atoi(in + 9); } else if (strncmp(in, "Content-Base:", 13) == 0) { free(sys->content_base); val = in + 13; skip_whitespace(val); sys->content_base = strdup(val); } else if (strncmp(in, "Content-Length:", 15) == 0) { val = in + 16; skip_whitespace(val); content_length = atoi(val); } else if (strncmp("Session:", in, 8) == 0) { val = in + 8; skip_whitespace(val); parse_session(val, sys->session_id, 64, &sys->keepalive_interval); } else if (strncmp("Transport:", in, 10) == 0) { val = in + 10; skip_whitespace(val); if (parse_transport(access, val) != 0) { rtsp_result = VLC_EGENERIC; break; } } else if (strncmp("com.ses.streamID:", in, 17) == 0) { val = in + 17; skip_whitespace(val); sys->stream_id = atoi(val); } else if (in[0] == '\0') { have_header = true; } free(in); } /* Discard further content */ while (content_length > 0 && (read = net_Read(access, sys->tcp_sock, buffer, __MIN(sizeof(buffer), content_length)))) content_length -= read; return rtsp_result; }
int main( int argc, char **argv ) { unsigned i; THREAD_DATA *tdata; int c; int temp, sdata; int got_esc = 0; DATA data; // Interpret arguments if( argc < 4 ) { fprintf( stderr, "Usage: %s <transport> <baud> <vcom1> [<vcom2>] ... [<vcomn>] [-v]\n", argv[ 0 ] ); return 1; } i = argc - 1; if( !strcasecmp( argv[ i ], "-v" ) ) { i --; log_init( LOG_ALL ); } else log_init( LOG_NONE ); if( ( vport_num = i - 2 ) > SERVICE_MAX ) { fprintf( stderr, "Too many service ports, maximum is %d\n", SERVICE_MAX ); return 1; } if( parse_transport( argv[ MAIN_TRANSPORT_IDX ] ) == 0 ) return 1; if( secure_atoi( argv[ SERVICE_BAUD_IDX ], &service_baud ) == 0 ) { fprintf( stderr, "Invalid service baud\n" ); return 1; } if( transport_init() == 0 ) return 1; // Create global sync objects sem_init( &mux_w_sem, 0, 1 ); sem_init( &mux_r_sem, 0, 0 ); // Open all the service ports and create their corresponding threads if( ( threads = ( THREAD_DATA* )malloc( sizeof( THREAD_DATA ) * ( vport_num + 1 ) ) ) == NULL ) { fprintf( stderr, "Not enough memory\n" ); return 1; } for( i = 0; i <= vport_num; i ++ ) { tdata = threads + i; if( i < vport_num ) { if( ( tdata->fd = ser_open( argv[ i + FIRST_SERVICE_IDX ] ) ) == ( ser_handler )-1 ) { fprintf( stderr, "Unable to open port %s\n", argv[ i + FIRST_SERVICE_IDX ] ); return 1; } if( ser_setup( tdata->fd, service_baud, SER_DATABITS_8, SER_PARITY_NONE, SER_STOPBITS_1 ) != SER_OK ) { fprintf( stderr, "Unable to setup serial port %s\n", argv[ i + FIRST_SERVICE_IDX ] ); return 1; } tdata->pname = argv[ i + FIRST_SERVICE_IDX ]; tdata->service_id = i + SERVICE_ID_FIRST; } if( pthread_create( &tdata->tid, NULL, i == vport_num ? transport_thread : service_thread, ( void* )tdata ) ) { fprintf( stderr, "Unable to create thread\n" ); return 1; } } printf( "Starting service multiplexer on %u port(s)\n", vport_num ); // Main service thread while( 1 ) { sem_wait( &mux_r_sem ); data = mux_data; sem_post( &mux_w_sem ); if( data.id == TRANSPORT_SERVICE_ID ) { // Read one byte, interpret it c = data.data; if( c != ESCAPE_CHAR ) { if( c >= SERVICE_ID_FIRST && c <= SERVICE_ID_LAST ) service_id_in = c; else { if( got_esc ) { // Got an escape last time, check the char now (with the 5th bit flipped) c ^= ESCAPE_XOR_MASK; if( c != ESCAPE_CHAR && c < SERVICE_ID_FIRST && c > SERVICE_ID_LAST ) { fprintf( stderr, "Protocol error: invalid escape sequence\n" ); return 1; } got_esc = 0; } if( service_id_in == -1 ) { fprintf( stderr, "Protocol error: service ID not specified\n" ); return 1; } ser_write_byte( threads[ service_id_in - SERVICE_ID_FIRST ].fd, c ); } } else got_esc = 1; } else { temp = data.id; sdata = data.data; if( temp != service_id_out ) transport_send_byte( temp ); // Then send the actual data byte, escaping it if needed if( sdata == ESCAPE_CHAR || ( sdata >= SERVICE_ID_FIRST && sdata <= SERVICE_ID_LAST ) ) { transport_send_byte( ESCAPE_CHAR ); transport_send_byte( ( u8 )sdata ^ ESCAPE_XOR_MASK ); } else transport_send_byte( sdata ); service_id_out = temp; } } return 0; }