Exemplo n.º 1
0
void free_kd(struct kdnode *t)
{
	if(t == NULL) return;
	else
	{
		if( t->loson != NULL) free_kd(t->loson);
		if( t->hison != NULL) free_kd(t->hison);
		free(t);
	}
}
Exemplo n.º 2
0
int raopcl_connect(raopcl_t *p, char *host,u_int16_t destport)
{
	u_int8_t buf[4+8+16];
	char sid[16];
	char sci[24];
	char *sac=NULL,*key=NULL,*iv=NULL;
	char sdp[1024];
	int rval=-1;
	key_data_t *setup_kd=NULL;
	char *aj, *token, *pc;
	const char delimiters[] = ";";
	u_int8_t rsakey[512];
	int i;
	raopcl_data_t *raopcld;
	if(!p) return -1;

	raopcld=(raopcl_data_t *)p;
	RAND_bytes(buf, sizeof(buf));
	sprintf(sid, "%d", *((u_int32_t*)buf));
	sprintf(sci, "%08x%08x",*((u_int32_t*)(buf+4)),*((u_int32_t*)(buf+8)));
	base64_encode(buf+12,16,&sac);
	if(!(raopcld->rtspcl=rtspcl_open())) goto erexit;
	if(rtspcl_set_useragent(raopcld->rtspcl,"iTunes/4.6 (Macintosh; U; PPC Mac OS X 10.3)")) goto erexit;
	if(rtspcl_add_exthds(raopcld->rtspcl,"Client-Instance", sci)) goto erexit;
	if(rtspcl_connect(raopcld->rtspcl, host, destport, sid)) goto erexit;

	i=rsa_encrypt(raopcld->key,16,rsakey);
	base64_encode(rsakey,i,&key);
	remove_char_from_string(key,'=');
	base64_encode(raopcld->iv,16,&iv);
	remove_char_from_string(iv,'=');
	sprintf(sdp,
            "v=0\r\n"
            "o=iTunes %s 0 IN IP4 %s\r\n"
            "s=iTunes\r\n"
            "c=IN IP4 %s\r\n"
            "t=0 0\r\n"
            "m=audio 0 RTP/AVP 96\r\n"
            "a=rtpmap:96 AppleLossless\r\n"
            "a=fmtp:96 4096 0 16 40 10 14 2 255 0 0 44100\r\n"
            "a=rsaaeskey:%s\r\n"
            "a=aesiv:%s\r\n",
            sid, rtspcl_local_ip(raopcld->rtspcl), host, key, iv);
	remove_char_from_string(sac,'=');
	if(rtspcl_add_exthds(raopcld->rtspcl, "Apple-Challenge", sac)) goto erexit;
	if(rtspcl_annouce_sdp(raopcld->rtspcl, sdp)) goto erexit;
	if(rtspcl_mark_del_exthds(raopcld->rtspcl, "Apple-Challenge")) goto erexit;
	if(rtspcl_setup(raopcld->rtspcl, &setup_kd)) goto erexit;
	if(!(aj=kd_lookup(setup_kd,"Audio-Jack-Status"))) {
		ERRMSG("%s: Audio-Jack-Status is missing\n",__func__);
		goto erexit;
	}
	
	token=strtok(aj,delimiters);
	while(token){
		if((pc=strstr(token,"="))){
			*pc=0;
			if(!strcmp(token,"type") && !strcmp(pc+1,"digital")){
				raopcld->ajtype=JACK_TYPE_DIGITAL;
			}
		}else{
			if(!strcmp(token,"connected")){
				raopcld->ajstatus=JACK_STATUS_CONNECTED;
			}
		}
		token=strtok(NULL,delimiters);
	}

	if(rtspcl_record(raopcld->rtspcl)) goto erexit;

	// keep host address and port information
	if(realloc_memory((void**)&raopcld->addr,strlen(host)+1,__func__)) goto erexit;
	strcpy(raopcld->addr,host);
	raopcld->rtsp_port=destport;

	if(raopcl_stream_connect(raopcld)) goto erexit;
	
	rval=0;
 erexit:
	if(sac) free(sac);
	if(key) free(key);
	if(iv) free(iv);
	free_kd(setup_kd);
	return rval;
	
	
}
Exemplo n.º 3
0
bool
rtspcl_setup(struct rtspcl_data *rtspcld, struct key_data **kd,
	     int control_port, int ntp_port,
	     GError **error_r)
{
	struct key_data *rkd = NULL, hds;
	const char delimiters[] = ";";
	char *buf = NULL;
	char *token, *pc;
	int rval = false;

	static char transport_key[] = "Transport";

	char transport_value[256];
	snprintf(transport_value, sizeof(transport_value),
		 "RTP/AVP/UDP;unicast;interleaved=0-1;mode=record;control_port=%d;timing_port=%d",
		 control_port, ntp_port);

	hds.key = transport_key;
	hds.data = transport_value;
	hds.next = NULL;
	if (!exec_request(rtspcld, "SETUP", NULL, NULL, 1,
			  &hds, &rkd, error_r))
		return false;

	if (!(rtspcld->session = g_strdup(kd_lookup(rkd, "Session")))) {
		g_set_error_literal(error_r, rtsp_client_quark(), 0,
				    "no session in response");
		goto erexit;
	}
	if (!(rtspcld->transport = kd_lookup(rkd, "Transport"))) {
		g_set_error_literal(error_r, rtsp_client_quark(), 0,
				    "no transport in response");
		goto erexit;
	}
	buf = g_strdup(rtspcld->transport);
	token = strtok(buf, delimiters);
	rtspcld->server_port = 0;
	rtspcld->control_port = 0;
	while (token) {
		if ((pc = strstr(token, "="))) {
			*pc = 0;
			if (!strcmp(token,"server_port")) {
				rtspcld->server_port=atoi(pc + 1);
			}
			if (!strcmp(token,"control_port")) {
				rtspcld->control_port=atoi(pc + 1);
			}
		}
		token = strtok(NULL, delimiters);
	}
	if (rtspcld->server_port == 0) {
		g_set_error_literal(error_r, rtsp_client_quark(), 0,
				    "no server_port in response");
		goto erexit;
	}
	if (rtspcld->control_port == 0) {
		g_set_error_literal(error_r, rtsp_client_quark(), 0,
				    "no control_port in response");
		goto erexit;
	}
	rval = true;
 erexit:
	g_free(buf);

	if (!rval || kd == NULL) {
		free_kd(rkd);
		rkd = NULL;
	}

	if (kd != NULL)
		*kd = rkd;

	return rval;
}
Exemplo n.º 4
0
/*
 * send RTSP request, and get response if it's needed
 * if this gets a success, *kd is allocated or reallocated (if *kd is not NULL)
 */
bool
exec_request(struct rtspcl_data *rtspcld, const char *cmd,
	     const char *content_type, const char *content,
	     int get_response,
	     const struct key_data *hds, struct key_data **kd,
	     GError **error_r)
{
	char line[1024];
	char req[1024];
	char reql[128];
	const char delimiters[] = " ";
	char *token, *dp;
	int dsize = 0;
	int timeout = 5000; // msec unit

	if (!rtspcld) {
		g_set_error_literal(error_r, rtsp_client_quark(), 0,
				    "not connected");
		return false;
	}

	sprintf(req, "%s %s RTSP/1.0\r\nCSeq: %d\r\n", cmd, rtspcld->url, ++rtspcld->cseq );

	if ( rtspcld->session != NULL ) {
		sprintf(reql,"Session: %s\r\n", rtspcld->session );
		strncat(req,reql,sizeof(req));
	}

	const struct key_data *hd_iter = hds;
	while (hd_iter) {
		sprintf(reql, "%s: %s\r\n", hd_iter->key, hd_iter->data);
		strncat(req, reql, sizeof(req));
		hd_iter = hd_iter->next;
	}

	if (content_type && content) {
		sprintf(reql, "Content-Type: %s\r\nContent-Length: %d\r\n",
			content_type, (int) strlen(content));
		strncat(req,reql,sizeof(req));
	}

	sprintf(reql, "User-Agent: %s\r\n", rtspcld->useragent);
	strncat(req, reql, sizeof(req));

	hd_iter = rtspcld->exthds;
	while (hd_iter) {
		sprintf(reql, "%s: %s\r\n", hd_iter->key, hd_iter->data);
		strncat(req, reql, sizeof(req));
		hd_iter = hd_iter->next;
	}
	strncat(req, "\r\n", sizeof(req));

	if (content_type && content)
		strncat(req, content, sizeof(req));

	if (!tcp_socket_send(rtspcld->tcp_socket, req, strlen(req))) {
		g_set_error(error_r, rtsp_client_quark(), errno,
			    "write error: %s",
			    g_strerror(errno));
		return false;
	}

	if (!get_response) return true;

	if (read_line(rtspcld, line, sizeof(line), timeout) <= 0) {
		g_set_error_literal(error_r, rtsp_client_quark(), 0,
				    "request failed");
		return false;
	}

	token = strtok(line, delimiters);
	token = strtok(NULL, delimiters);
	if (token == NULL) {
		g_set_error_literal(error_r, rtsp_client_quark(), 0,
				    "request failed");
		return false;
	}

	if (strcmp(token, "200") != 0) {
		g_set_error(error_r, rtsp_client_quark(), 0,
			    "request failed: %s", token);
		return false;
	}

	/* if the caller isn't interested in response headers, put
	   them on the trash, which is freed before returning from
	   this function */
	struct key_data *trash = NULL;
	if (kd == NULL)
		kd = &trash;

	struct key_data *cur_kd = *kd;

	struct key_data *new_kd = NULL;
	while (read_line(rtspcld, line, sizeof(line), timeout) > 0) {
		timeout = 1000; // once it started, it shouldn't take a long time
		if (new_kd != NULL && line[0] == ' ') {
			const char *j = line;
			while (*j == ' ')
				++j;

			dsize += strlen(j);
			new_kd->data = g_realloc(new_kd->data, dsize);
			strcat(new_kd->data, j);
			continue;
		}
		dp = strstr(line, ":");
		if (!dp) {
			free_kd(*kd);
			*kd = NULL;

			g_set_error_literal(error_r, rtsp_client_quark(), 0,
					    "request failed, bad header");
			return false;
		}

		*dp++ = 0;
		new_kd = g_new(struct key_data, 1);
		new_kd->key = g_strdup(line);
		dsize = strlen(dp) + 1;
		new_kd->data = g_strdup(dp);
		new_kd->next = NULL;
		if (cur_kd == NULL) {
			cur_kd = *kd = new_kd;
		} else {
			cur_kd->next = new_kd;
			cur_kd = new_kd;
		}
	}

	free_kd(trash);

	return true;
}
Exemplo n.º 5
0
static void
rtspcl_remove_all_exthds(struct rtspcl_data *rtspcld)
{
	free_kd(rtspcld->exthds);
	rtspcld->exthds = NULL;
}
Exemplo n.º 6
0
/*
 * send RTSP request, and get responce if it's needed
 * if this gets a success, *kd is allocated or reallocated (if *kd is not NULL)
 */
static int exec_request(rtspcl_data_t *rtspcld, char *cmd, char *content_type,
                char *content, int length, int get_response, key_data_t *hds, key_data_t **kd, char* url)
{
    char line[2048];
    char req[1024];
    char reql[128];
    const char delimiters[] = " ";
    char *token,*dp;
    int i,j,dsize,rval,totallength;
    int timeout=5000; // msec unit

    if(!rtspcld) return -1;

    if(url==NULL)
    {
        sprintf(req, "%s %s RTSP/1.0\r\n",cmd,rtspcld->url);
    }
    else
    {
        sprintf(req, "%s %s RTSP/1.0\r\n",cmd,url);
    }
    i=0;
    while( hds && hds[i].key != NULL )
    {
        sprintf(reql,"%s: %s\r\n", hds[i].key, hds[i].data);
        strncat(req,reql,sizeof(req));
        i++;
    }

    if( content_type && content) 
    {
        if(!length)
        {
            sprintf(reql, "Content-Type: %s\r\nContent-Length: %d\r\n",
            content_type, (int)strlen(content));
        }
        else
        {
            sprintf(reql, "Content-Type: %s\r\nContent-Length: %d\r\n",
            content_type, length);
        }
        strncat(req,reql,sizeof(req));
    }
    
    sprintf(reql,"CSeq: %d\r\n",++rtspcld->cseq);
    strncat(req,reql,sizeof(req));
    
    sprintf(reql, "User-Agent: %s\r\n", rtspcld->useragent );
    strncat(req,reql,sizeof(req));

    i=0;
    while(rtspcld->exthds && rtspcld->exthds[i].key)
    {
        if(rtspcld->exthds[i].key[0]==0xff) {i++;continue;}
        sprintf(reql,"%s: %s\r\n", rtspcld->exthds[i].key, rtspcld->exthds[i].data);
        strncat(req,reql,sizeof(req));
        i++;
    }
    
    if( rtspcld->session != NULL )
    {
        sprintf(reql,"Session: %s\r\n",rtspcld->session);
        strncat(req,reql,sizeof(req));
    }
    
    strncat(req,"\r\n",sizeof(req));

    if( content_type && content)
    {
        if(!length)
        {
            strncat(req,content,sizeof(req));
        }
        else
        {
            totallength = strlen(req) + length;
            memcpy(req+strlen(req),content,length);
        }
    }

    if(!length)
    {
        rval=write(rtspcld->fd,req,strlen(req));
        DBGMSG("----> %s : write %s\n",__func__, req);
        if ( rval != strlen(req) )
        {
           ERRMSG("couldn't write request (%d!=%d)\n",(int)rval,(int)strlen(req));
        }
    }
    else
    {
        rval=write(rtspcld->fd,req,totallength);
        DBGMSG("----> %s : write %s\n",__func__,req);
        if ( rval != totallength )
        {
           ERRMSG("couldn't write request (%d!=%d)\n",rval,totallength);
        }
    }

    if( !get_response ) return 0;
    
    if(read_line(rtspcld->fd,line,sizeof(line),timeout,0)<=0)    
    {
        if(get_response==1)
        {
            ERRMSG("%s: response : %s request failed\n",__func__, line);
            return -1;
        }
        else
        {
            return 0;
        }
    }

    token = strtok(line, delimiters);
    token = strtok(NULL, delimiters);
    if(token==NULL || strcmp(token,"200"))
    {
        if(get_response==1)
        {
            ERRMSG("<------ : %s: request failed, error %s\n",__func__,line);
            return -1;
        }
    }
    else
    {
        DBGMSG("<------ : %s: request ok (%s)\n",__func__,token);
    }

    i=0;
    while(read_line(rtspcld->fd,line,sizeof(line),timeout,0)>0){
        DBGMSG("<------ : %s\n",line);
        timeout=1000; // once it started, it shouldn't take a long time
        if(i%16==0){
            if(realloc_memory((void*)kd,(16*(i/16+1)+1)*sizeof(key_data_t),__func__)) return -1;
            memset(*kd+16*(i/16),0,17*sizeof(key_data_t));
        }

        if(i && line[0]==' '){
            for(j=0;j<strlen(line);j++) if(line[j]!=' ') break;
            dsize+=strlen(line+j);
            if(realloc_memory((void*)&(*kd)[i].data,dsize,__func__)) return -1;
            strcat((char*)(*kd)[i].data,line+j);
            continue;
        }

        dp=strstr(line,":");

        if(!dp){
            ERRMSG("%s: Request failed, bad header\n",__func__);
            free_kd(*kd);
            *kd=NULL;
            return -1;
        }

        *dp=0;
        if(realloc_memory((void*)&(*kd)[i].key,strlen(line)+1,__func__)) return -1;
        strcpy((char*)(*kd)[i].key,line);
        dsize=strlen(dp+1)+1;
        if(realloc_memory((void*)&(*kd)[i].data,dsize,__func__)) return -1;
        strcpy((char*)(*kd)[i].data,dp+1);
        i++;

        if ( strcmp( line, "Audio-Latency" ) == 0 )
        {
           alatency=atoi( dp+2 );
           DBGMSG( "saving latency : %d\n", alatency );
        }
    }
    while(read_line(rtspcld->fd,line,sizeof(line),timeout,0)>0)
    {
        //read body
        DBGMSG("<------ : %s\n",line);
    }
    (*kd)[i].key=NULL;
    return 0;
}
Exemplo n.º 7
0
int rtspcl_setup(rtspcl_t *p, key_data_t **kd)
{
    key_data_t *rkd=NULL;
    key_data_t hds[2];
    const char delimiters[] = ";";
    char *buf=NULL;
    char *token,*pc;
    char *temp;
    int rval=-1;
    rtspcl_data_t *rtspcld;

    if(!p) return -1;
    rtspcld=(rtspcl_data_t *)p;
    hds[0].key=(uint8_t*)"Transport";
    hds[0].data=(uint8_t*)"RTP/AVP/UDP;unicast;interleaved=0-1;mode=record;control_port=6001;timing_port=6002";
    hds[1].key=NULL;
    if(exec_request(rtspcld, "SETUP", NULL, NULL, 0, 1, hds, &rkd, NULL)) return -1;
    if(!(temp=kd_lookup(rkd, "Session"))){
        ERRMSG("%s: no session in response\n",__func__);
        goto erexit;
    }
    DBGMSG("<------- : %s: session:%s\n",__func__,temp);
    rtspcld->session = (char *) malloc(100);
    sprintf( rtspcld->session, "%s", trim(temp) );
    if(!(rtspcld->transport=kd_lookup(rkd, "Transport"))){
        ERRMSG("%s: no transport in responce\n",__func__);
        goto erexit;
    }
    if(realloc_memory((void*)&buf,strlen(rtspcld->transport)+1,__func__)) goto erexit;
    strcpy(buf,rtspcld->transport);
    token=strtok(buf,delimiters);
    rtspcld->server_port=0;
    while(token)
    {
        if((pc=strstr(token,"=")))
        {
            *pc=0;
            if(!strcmp(token,"server_port"))
            {
                rtspcld->server_port=atoi(pc+1);
                DBGMSG( "got server port : %d\n", rtspcld->server_port );
            }
            if(!strcmp(token,"control_port"))
            {
                rtspcld->control_port=atoi(pc+1);
                DBGMSG( "got control port : %d\n", rtspcld->control_port );
            }
            if(!strcmp(token,"timing_port"))
            {
                rtspcld->timing_port=atoi(pc+1);
                DBGMSG( "got timing port : %d\n", rtspcld->timing_port );
            }
        }
        token=strtok(NULL,delimiters);
    }
    if(rtspcld->server_port==0){
        ERRMSG("%s: no server_port in response\n",__func__);
        goto erexit;
    }
    rval=0;
 erexit:
    if(buf) free(buf);
    if(rval) {
        free_kd(rkd);
        rkd=NULL;
    }
    *kd=rkd;
    return rval;
}