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; }
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; }
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; }