Author: gmaruzz Date: Mon Feb 9 13:25:18 2009 New Revision: 11719 Log: skypiax: cleaning skypiax_protocol.c Modified: freeswitch/branches/gmaruzz/mod_skypiax/mod_skypiax.c freeswitch/branches/gmaruzz/mod_skypiax/skypiax_protocol.c Modified: freeswitch/branches/gmaruzz/mod_skypiax/mod_skypiax.c ============================================================================== --- freeswitch/branches/gmaruzz/mod_skypiax/mod_skypiax.c (original) +++ freeswitch/branches/gmaruzz/mod_skypiax/mod_skypiax.c Mon Feb 9 13:25:18 2009 @@ -1058,13 +1058,16 @@ if (channel) { switch_dtmf_t dtmf = { (char) value[0], switch_core_default_dtmf_duration(0) }; - DEBUGA_SKYPE("%c DTMF %s\n", SKYPIAX_P_LOG, dtmf.digit, + NOTICA("received DTMF %c on channel %s\n", SKYPIAX_P_LOG, dtmf.digit, switch_channel_get_name(channel)); switch_mutex_lock(tech_pvt->flag_mutex); + //FIXME: why sometimes DTMFs from here do not seems to be get by FS? switch_channel_queue_dtmf(channel, &dtmf); switch_set_flag(tech_pvt, TFLAG_DTMF); switch_mutex_unlock(tech_pvt->flag_mutex); - } + } else { + WARNINGA("received %c DTMF, but no channel?\n", SKYPIAX_P_LOG, value[0]); + } switch_core_session_rwunlock(session); return 0; Modified: freeswitch/branches/gmaruzz/mod_skypiax/skypiax_protocol.c ============================================================================== --- freeswitch/branches/gmaruzz/mod_skypiax/skypiax_protocol.c (original) +++ freeswitch/branches/gmaruzz/mod_skypiax/skypiax_protocol.c Mon Feb 9 13:25:18 2009 @@ -23,309 +23,8 @@ #endif /* WIN32 */ /*************************************/ -void *skypiax_do_tcp_srv_thread_func(void *obj) -{ - private_t *tech_pvt = obj; - int s; - unsigned int len; - unsigned int i; - unsigned int a; -#if defined(WIN32) && !defined(__CYGWIN__) - int sin_size; -#else /* WIN32 */ - unsigned int sin_size; -#endif /* WIN32 */ - unsigned int fd; - short srv_in[SAMPLES_PER_FRAME]; - short srv_out[SAMPLES_PER_FRAME / 2]; - struct sockaddr_in my_addr; - struct sockaddr_in remote_addr; - int exit = 0; - unsigned int kill_cli_size; - short kill_cli_buff[SAMPLES_PER_FRAME]; - short totalbuf[SAMPLES_PER_FRAME]; - - memset(&my_addr, 0, sizeof(my_addr)); - my_addr.sin_family = AF_INET; - my_addr.sin_addr.s_addr = htonl(0x7f000001); /* use the localhost */ - my_addr.sin_port = htons(tech_pvt->tcp_srv_port); - - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - ERRORA("socket Error\n", SKYPIAX_P_LOG); - return NULL; - } - - if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { - ERRORA("bind Error\n", SKYPIAX_P_LOG); - return NULL; - } - DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG); - - listen(s, 6); - - sin_size = sizeof(remote_addr); - while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) { - DEBUGA_SKYPE("ACCEPTED\n", SKYPIAX_P_LOG); - if (!running) - break; - while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN - && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS - || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) { - - unsigned int fdselect; - int rt; - fd_set fs; - struct timeval to; - - if (!running) - break; - exit = 1; - - fdselect = fd; - FD_ZERO(&fs); - FD_SET(fdselect, &fs); - to.tv_usec = 2000000; //2000 msec - to.tv_sec = 0; - - rt = select(fdselect + 1, &fs, NULL, NULL, &to); - if (rt > 0) { - - len = recv(fd, (char *) srv_in, 320, 0); //seems that Skype only sends 320 bytes at time - - if (len == 320) { - unsigned int howmany; - - if (SAMPLERATE_SKYPIAX == 8000) { - /* we're downsampling from 16khz to 8khz, srv_out will contain each other sample from srv_in */ - a = 0; - for (i = 0; i < len / sizeof(short); i++) { - srv_out[a] = srv_in[i]; - i++; - a++; - } - } else if (SAMPLERATE_SKYPIAX == 16000) { - /* we're NOT downsampling, srv_out will contain ALL samples from srv_in */ - for (i = 0; i < len / sizeof(short); i++) { - srv_out[i] = srv_in[i]; - } - } else { - ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG); - } - /* if not yet done, let's store the half incoming frame */ - if (!tech_pvt->audiobuf_is_loaded) { - for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) { - tech_pvt->audiobuf[i] = srv_out[i]; - } - tech_pvt->audiobuf_is_loaded = 1; - } else { - /* we got a stored half frame, build a complete frame in totalbuf using the stored half frame and the current half frame */ - for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) { - totalbuf[i] = tech_pvt->audiobuf[i]; - } - for (a = 0; a < SAMPLES_PER_FRAME / 2; a++) { - totalbuf[i] = srv_out[a]; - i++; - } - /* send the complete frame through the pipe to our code waiting for incoming audio */ - howmany = - skypiax_pipe_write(tech_pvt->audiopipe[1], totalbuf, - SAMPLES_PER_FRAME * sizeof(short)); - if (howmany != SAMPLES_PER_FRAME * sizeof(short)) { - ERRORA("howmany is %d, but was expected to be %d\n", SKYPIAX_P_LOG, howmany, - SAMPLES_PER_FRAME * sizeof(short)); - } - /* done with the stored half frame */ - tech_pvt->audiobuf_is_loaded = 0; - } - - } else if (len == 0) { - DEBUGA_SKYPE("Skype incoming audio GONE\n", SKYPIAX_P_LOG); - skypiax_sleep(1000); - } else { - ERRORA("len=%d\n", SKYPIAX_P_LOG, len); - exit = 1; - break; - } - - } else { - if (rt) - ERRORA("SRV rt=%d\n", SKYPIAX_P_LOG, rt); - skypiax_sleep(10000); - } - - } - - /* let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die */ - kill_cli_size = SAMPLES_PER_FRAME * sizeof(short); - len = skypiax_pipe_write(tech_pvt->audiopipe[1], kill_cli_buff, kill_cli_size); - kill_cli_size = SAMPLES_PER_FRAME * sizeof(short); - len = skypiax_pipe_write(tech_pvt->audioskypepipe[1], kill_cli_buff, kill_cli_size); - tech_pvt->interface_state = SKYPIAX_STATE_DOWN; - kill_cli_size = SAMPLES_PER_FRAME * sizeof(short); - len = skypiax_pipe_write(tech_pvt->audiopipe[1], kill_cli_buff, kill_cli_size); - kill_cli_size = SAMPLES_PER_FRAME * sizeof(short); - len = skypiax_pipe_write(tech_pvt->audioskypepipe[1], kill_cli_buff, kill_cli_size); - - DEBUGA_SKYPE("Skype incoming audio GONE\n", SKYPIAX_P_LOG); - skypiax_close_socket(fd); - if (exit) - break; - } - - DEBUGA_SKYPE("incoming audio server (I am it) GONE\n", SKYPIAX_P_LOG); - skypiax_close_socket(s); - return NULL; -} - -void *skypiax_do_tcp_cli_thread_func(void *obj) -{ - private_t *tech_pvt = obj; - int s; - struct sockaddr_in my_addr; - struct sockaddr_in remote_addr; - unsigned int got; - unsigned int len; - unsigned int i; - unsigned int a; - unsigned int fd; - short cli_out[SAMPLES_PER_FRAME * 2]; - short cli_in[SAMPLES_PER_FRAME]; -#ifdef WIN32 - int sin_size; -#else - unsigned int sin_size; -#endif /* WIN32 */ - - memset(&my_addr, 0, sizeof(my_addr)); - my_addr.sin_family = AF_INET; - my_addr.sin_addr.s_addr = htonl(0x7f000001); /* use the localhost */ - my_addr.sin_port = htons(tech_pvt->tcp_cli_port); - - if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - ERRORA("socket Error\n", SKYPIAX_P_LOG); - return NULL; - } - - if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { - ERRORA("bind Error\n", SKYPIAX_P_LOG); - skypiax_close_socket(s); - return NULL; - } - DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG); - - listen(s, 6); - - sin_size = sizeof(remote_addr); - while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) { - DEBUGA_SKYPE("ACCEPTED\n", SKYPIAX_P_LOG); - if (!running) - break; - while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN - && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS - || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) { - unsigned int fdselect; - int rt; - fd_set fs; - struct timeval to; - - if (!running) - break; - fdselect = fd; - FD_ZERO(&fs); - FD_SET(fdselect, &fs); - to.tv_usec = 2000000; //2000 msec - to.tv_sec = 0; - - rt = select(fdselect + 1, NULL, &fs, NULL, &to); - - if (rt > 0) { - - /* read from the pipe the audio frame we are supposed to send out */ - got = - skypiax_pipe_read(tech_pvt->audioskypepipe[0], cli_in, - SAMPLES_PER_FRAME * sizeof(short)); - if (got != SAMPLES_PER_FRAME * sizeof(short)) { - WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, - SAMPLES_PER_FRAME * sizeof(short)); - } - - if (got == SAMPLES_PER_FRAME * sizeof(short)) { - if (SAMPLERATE_SKYPIAX == 8000) { - - /* we're upsampling from 8khz to 16khz, cli_out will contain two times each sample from cli_in */ - a = 0; - for (i = 0; i < got / sizeof(short); i++) { - cli_out[a] = cli_in[i]; - a++; - cli_out[a] = cli_in[i]; - a++; - } - got = got * 2; - } else if (SAMPLERATE_SKYPIAX == 16000) { - /* we're NOT upsampling, cli_out will contain just ALL samples from cli_in */ - for (i = 0; i < got / sizeof(short); i++) { - cli_out[i] = cli_in[i]; - } - } else { - ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG); - } - - /* send the 16khz frame to the Skype client waiting for incoming audio */ - len = send(fd, (char *) cli_out, got, 0); - - if (len == -1) { - break; - } else if (len != got) { - ERRORA("len=%d\n", SKYPIAX_P_LOG, len); - skypiax_sleep(1000); - break; - } - - } else { - - WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, - SAMPLES_PER_FRAME * sizeof(short)); - } - } else { - if (rt) - ERRORA("CLI rt=%d\n", SKYPIAX_P_LOG, rt); - skypiax_sleep(10000); - } - - } - DEBUGA_SKYPE("Skype outbound audio GONE\n", SKYPIAX_P_LOG); - skypiax_close_socket(fd); - break; - } - - DEBUGA_SKYPE("outbound audio server (I am it) GONE\n", SKYPIAX_P_LOG); - skypiax_close_socket(s); - return NULL; -} - -int skypiax_skypeaudio_read(private_t * tech_pvt) -{ - unsigned int samples; - - samples = - skypiax_pipe_read(tech_pvt->audiopipe[0], tech_pvt->read_frame.data, - SAMPLES_PER_FRAME * sizeof(short)); - - if (samples != SAMPLES_PER_FRAME * sizeof(short)) { - if (samples) - WARNINGA("read samples=%u expected=%u\n", SKYPIAX_P_LOG, samples, - SAMPLES_PER_FRAME * sizeof(short)); - return 0; - } else { - /* A real frame */ - tech_pvt->read_frame.datalen = samples; - } - return 1; -} - int skypiax_skype_read(private_t * tech_pvt) { - char read_from_pipe[4096]; char message[4096]; char message_2[4096]; @@ -361,9 +60,8 @@ skypiax_sleep(10000); return 0; } - if (!strncasecmp(message, "ERROR 92 CALL", 12)) { - ERRORA("Skype got ERROR: |||%s|||, the number we called was not recognized\n", + ERRORA("Skype got ERROR: |||%s|||, the (skypeout) number we called was not recognized as valid\n", SKYPIAX_P_LOG, message); tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG); @@ -376,9 +74,7 @@ tech_pvt->interface_state = SKYPIAX_STATE_DOWN; } } - strncpy(message_2, message, sizeof(message) - 1); - buf = message; stringp = &buf; where = strsep(stringp, " "); @@ -386,7 +82,7 @@ WARNINGA("Skype MSG without spaces: %s\n", SKYPIAX_P_LOG, message); } if (!strcasecmp(message, "ERROR")) { - ERRORA("Skype got ERROR: |||%s|||\n", SKYPIAX_P_LOG, message); + WARNINGA("Skype got ERROR: |||%s|||\n", SKYPIAX_P_LOG, message); tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; DEBUGA_SKYPE("skype_call now is DOWN\n", SKYPIAX_P_LOG); tech_pvt->skype_call_id[0] = '\0'; @@ -400,11 +96,8 @@ } if (!strcasecmp(message, "CURRENTUSERHANDLE")) { strncpy(obj, where, sizeof(obj) - 1); - where = strsep(stringp, " "); - strncpy(id, where, sizeof(id) - 1); - if (!strcasecmp(id, tech_pvt->skype_user)) { tech_pvt->SkypiaxHandles.api_connected = 1; DEBUGA_SKYPE @@ -412,309 +105,557 @@ SKYPIAX_P_LOG, message, obj, id, tech_pvt->skype_user); } } - if (!strcasecmp(message, "USER")) { strncpy(obj, where, sizeof(obj) - 1); - where = strsep(stringp, " "); - strncpy(id, where, sizeof(id) - 1); - where = strsep(stringp, " "); + strncpy(prop, where, sizeof(prop) - 1); + if (!strcasecmp(prop, "RECEIVEDAUTHREQUEST")) { + char msg_to_skype[256]; + DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", + SKYPIAX_P_LOG, message, obj, id, prop); + //TODO: allow authorization based on config param + sprintf(msg_to_skype, "SET USER %s ISAUTHORIZED TRUE", id); + skypiax_skype_write(tech_pvt, msg_to_skype); + } + } + if (!strcasecmp(message, "MESSAGE")) { + strncpy(obj, where, sizeof(obj) - 1); + where = strsep(stringp, " "); + strncpy(id, where, sizeof(id) - 1); + where = strsep(stringp, " "); + strncpy(prop, where, sizeof(prop) - 1); + if (!strcasecmp(prop, "STATUS")) { + where = strsep(stringp, " "); + strncpy(value, where, sizeof(value) - 1); + if (!strcasecmp(value, "RECEIVED")) { + char msg_to_skype[256]; + DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s value: %s!\n", + SKYPIAX_P_LOG, message, obj, id, prop, value); + //TODO: authomatically flag messages as read based on config param + sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id); + skypiax_skype_write(tech_pvt, msg_to_skype); + } + } else if (!strcasecmp(prop, "BODY")) { + char msg_to_skype[256]; + DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", + SKYPIAX_P_LOG, message, obj, id, prop); + //TODO: authomatically flag messages as read based on config param + sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id); + skypiax_skype_write(tech_pvt, msg_to_skype); + } + } + if (!strcasecmp(message, "CALL")) { + strncpy(obj, where, sizeof(obj) - 1); + where = strsep(stringp, " "); + strncpy(id, where, sizeof(id) - 1); + where = strsep(stringp, " "); + strncpy(prop, where, sizeof(prop) - 1); + where = strsep(stringp, " "); + strncpy(value, where, sizeof(value) - 1); + where = strsep(stringp, " "); + + DEBUGA_SKYPE + ("Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n", + SKYPIAX_P_LOG, message, obj, id, prop, value, where ? where : "NULL"); + + if (!strcasecmp(prop, "PARTNER_HANDLE")) { + strncpy(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1); + DEBUGA_SKYPE + ("the skype_call %s caller PARTNER_HANDLE (tech_pvt->callid_number) is: %s\n", + SKYPIAX_P_LOG, id, tech_pvt->callid_number); + return CALLFLOW_INCOMING_RING; + } + if (!strcasecmp(prop, "PARTNER_DISPNAME")) { + snprintf(tech_pvt->callid_name, sizeof(tech_pvt->callid_name) - 1, "%s%s%s", + value, where ? " " : "", where ? where : ""); + DEBUGA_SKYPE + ("the skype_call %s caller PARTNER_DISPNAME (tech_pvt->callid_name) is: %s\n", + SKYPIAX_P_LOG, id, tech_pvt->callid_name); + } + if (!strcasecmp(prop, "CONF_ID") && !strcasecmp(value, "0")) { + DEBUGA_SKYPE("the skype_call %s is NOT a conference call\n", SKYPIAX_P_LOG, id); + if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN) + tech_pvt->interface_state = SKYPIAX_STATE_PRERING; + } + if (!strcasecmp(prop, "CONF_ID") && strcasecmp(value, "0")) { + DEBUGA_SKYPE("the skype_call %s is a conference call\n", SKYPIAX_P_LOG, id); + if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN) + tech_pvt->interface_state = SKYPIAX_STATE_PRERING; + } + if (!strcasecmp(prop, "DTMF")) { + NOTICA("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value); + dtmf_received(tech_pvt, value); + } + if (!strcasecmp(prop, "FAILUREREASON")) { + DEBUGA_SKYPE + ("Skype FAILED on skype_call %s. Let's wait for the FAILED message.\n", + SKYPIAX_P_LOG, id); + } + if (!strcasecmp(prop, "DURATION") && (!strcasecmp(value, "1"))) { + if (strcasecmp(id, tech_pvt->skype_call_id)) { + strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + DEBUGA_SKYPE + ("We called a Skype contact and he answered us on skype_call: %s.\n", + SKYPIAX_P_LOG, id); + } + } + if (!strcasecmp(prop, "STATUS")) { + + if (!strcasecmp(value, "RINGING")) { + char msg_to_skype[1024]; + if (tech_pvt->interface_state != SKYPIAX_STATE_DIALING) { + /* we are not calling out */ + if (!strlen(tech_pvt->skype_call_id)) { + /* we are not inside an active call */ + tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING; + tech_pvt->interface_state = SKYPIAX_STATE_RING; + /* no owner, no active call, let's answer */ + skypiax_skype_write(tech_pvt, "SET AGC OFF"); + skypiax_sleep(10000); + skypiax_skype_write(tech_pvt, "SET AEC OFF"); + skypiax_sleep(10000); + sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id); + skypiax_skype_write(tech_pvt, msg_to_skype); + skypiax_sleep(10000); + sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id); + skypiax_skype_write(tech_pvt, msg_to_skype); + skypiax_sleep(10000); + sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id); + skypiax_skype_write(tech_pvt, msg_to_skype); + DEBUGA_SKYPE("We answered a Skype RING on skype_call %s\n", SKYPIAX_P_LOG, + id); + strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + } else { + /* we're owned, we're in a call, let's refuse */ + sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); + skypiax_skype_write(tech_pvt, msg_to_skype); + skypiax_sleep(10000); + DEBUGA_SKYPE + ("We have NOT answered a Skype RING on skype_call %s, because we are already in a skypiax call\n", + SKYPIAX_P_LOG, id); + } + } else { + /* we are calling out */ + tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING; + tech_pvt->interface_state = SKYPIAX_STATE_RINGING; + strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + DEBUGA_SKYPE("Our remote party in skype_call %s is RINGING\n", + SKYPIAX_P_LOG, id); + } + } else if (!strcasecmp(value, "EARLYMEDIA")) { + tech_pvt->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA; + tech_pvt->interface_state = SKYPIAX_STATE_DIALING; + DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n", + SKYPIAX_P_LOG, id); + } else if (!strcasecmp(value, "MISSED")) { + DEBUGA_SKYPE("We missed skype_call %s\n", SKYPIAX_P_LOG, id); + } else if (!strcasecmp(value, "FINISHED")) { + DEBUGA_SKYPE("skype_call %s now is DOWN\n", SKYPIAX_P_LOG, id); + tech_pvt->skype_call_id[0] = '\0'; + if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) { + //tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + return CALLFLOW_INCOMING_HANGUP; + } else { + tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + } + } else if (!strcasecmp(value, "CANCELLED")) { + tech_pvt->skype_callflow = CALLFLOW_STATUS_CANCELLED; + DEBUGA_SKYPE + ("we tried to call Skype on skype_call %s and Skype has now CANCELLED\n", + SKYPIAX_P_LOG, id); + tech_pvt->skype_call_id[0] = '\0'; + if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) { + tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + return CALLFLOW_INCOMING_HANGUP; + } else { + tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + } + } else if (!strcasecmp(value, "FAILED")) { + tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED; + DEBUGA_SKYPE + ("we tried to call Skype on skype_call %s and Skype has now FAILED\n", + SKYPIAX_P_LOG, id); + tech_pvt->skype_call_id[0] = '\0'; + strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + return CALLFLOW_INCOMING_HANGUP; + } else if (!strcasecmp(value, "REFUSED")) { + if (!strcasecmp(id, tech_pvt->skype_call_id)) { + /* this is the id of the call we are in, probably we generated it */ + tech_pvt->skype_callflow = CALLFLOW_STATUS_REFUSED; + DEBUGA_SKYPE + ("we tried to call Skype on skype_call %s and Skype has now REFUSED\n", + SKYPIAX_P_LOG, id); + strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + tech_pvt->skype_call_id[0] = '\0'; + return CALLFLOW_INCOMING_HANGUP; + } else { + /* we're here because were us that refused an incoming call */ + DEBUGA_SKYPE("we REFUSED skype_call %s\n", SKYPIAX_P_LOG, id); + } + } else if (!strcasecmp(value, "ROUTING")) { + tech_pvt->skype_callflow = CALLFLOW_STATUS_ROUTING; + tech_pvt->interface_state = SKYPIAX_STATE_DIALING; + strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + DEBUGA_SKYPE("skype_call: %s is now ROUTING\n", SKYPIAX_P_LOG, id); + } else if (!strcasecmp(value, "UNPLACED")) { + tech_pvt->skype_callflow = CALLFLOW_STATUS_UNPLACED; + tech_pvt->interface_state = SKYPIAX_STATE_DIALING; + strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + DEBUGA_SKYPE("skype_call: %s is now UNPLACED\n", SKYPIAX_P_LOG, id); + } else if (!strcasecmp(value, "INPROGRESS")) { + char msg_to_skype[1024]; + tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS; + strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); + tech_pvt->interface_state = SKYPIAX_STATE_UP; + DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPIAX_P_LOG, id); + sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, + tech_pvt->tcp_cli_port); + skypiax_skype_write(tech_pvt, msg_to_skype); + start_audio_threads(tech_pvt); + sprintf(msg_to_skype, "ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, + tech_pvt->tcp_srv_port); + skypiax_skype_write(tech_pvt, msg_to_skype); + tech_pvt->skype_callflow = SKYPIAX_STATE_UP; + if (!strlen(tech_pvt->session_uuid_str)) { + DEBUGA_SKYPE("New Inbound Channel!\n", SKYPIAX_P_LOG); + new_inbound_channel(tech_pvt); + } else { + DEBUGA_SKYPE("Outbound Channel Answered!\n", SKYPIAX_P_LOG); + outbound_channel_answered(tech_pvt); + } + } else { + WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPIAX_P_LOG, id, + value); + } + } //STATUS + } //CALL + /* the "numbered" messages that follows are used by the directory application, not yet ported */ + if (!strcasecmp(message, "#333")) { + /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[11]: %s\n", SKYPIAX_P_LOG, + * message_2, &message_2[11]); */ + memset(tech_pvt->skype_friends, 0, 4096); + strncpy(tech_pvt->skype_friends, &message_2[11], 4095); + } + if (!strcasecmp(message, "#222")) { + /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG, + * message_2, &message_2[10]); */ + memset(tech_pvt->skype_fullname, 0, 512); + strncpy(tech_pvt->skype_fullname, &message_2[10], 511); + } + if (!strcasecmp(message, "#765")) { + /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG, + * message_2, &message_2[10]); */ + memset(tech_pvt->skype_displayname, 0, 512); + strncpy(tech_pvt->skype_displayname, &message_2[10], 511); + } + a = 0; + } //message end + } //read_from_pipe + return 0; +} - strncpy(prop, where, sizeof(prop) - 1); +void *skypiax_do_tcp_srv_thread_func(void *obj) +{ + private_t *tech_pvt = obj; + int s; + unsigned int len; + unsigned int i; + unsigned int a; +#if defined(WIN32) && !defined(__CYGWIN__) + int sin_size; +#else /* WIN32 */ + unsigned int sin_size; +#endif /* WIN32 */ + unsigned int fd; + short srv_in[SAMPLES_PER_FRAME]; + short srv_out[SAMPLES_PER_FRAME / 2]; + struct sockaddr_in my_addr; + struct sockaddr_in remote_addr; + int exit = 0; + unsigned int kill_cli_size; + short kill_cli_buff[SAMPLES_PER_FRAME]; + short totalbuf[SAMPLES_PER_FRAME]; - if (!strcasecmp(prop, "RECEIVEDAUTHREQUEST")) { - char msg_to_skype[256]; - DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", - SKYPIAX_P_LOG, message, obj, id, prop); + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = htonl(0x7f000001); /* use the localhost */ + my_addr.sin_port = htons(tech_pvt->tcp_srv_port); - //FIXME: TODO: allow authorization based on config param - sprintf(msg_to_skype, "SET USER %s ISAUTHORIZED TRUE", id); - skypiax_skype_write(tech_pvt, msg_to_skype); - } - } + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ERRORA("socket Error\n", SKYPIAX_P_LOG); + return NULL; + } - if (!strcasecmp(message, "MESSAGE")) { - strncpy(obj, where, sizeof(obj) - 1); + if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { + ERRORA("bind Error\n", SKYPIAX_P_LOG); + return NULL; + } + DEBUGA_SKYPE("started tcp_srv_thread thread.\n", SKYPIAX_P_LOG); - where = strsep(stringp, " "); + listen(s, 6); - strncpy(id, where, sizeof(id) - 1); + sin_size = sizeof(remote_addr); + while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) { + DEBUGA_SKYPE("ACCEPTED\n", SKYPIAX_P_LOG); + if (!running) + break; + while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN + && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS + || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) { - where = strsep(stringp, " "); + unsigned int fdselect; + int rt; + fd_set fs; + struct timeval to; - strncpy(prop, where, sizeof(prop) - 1); + if (!running) + break; + exit = 1; - if (!strcasecmp(prop, "STATUS")) { + fdselect = fd; + FD_ZERO(&fs); + FD_SET(fdselect, &fs); + to.tv_usec = 2000000; //2000 msec + to.tv_sec = 0; - where = strsep(stringp, " "); + rt = select(fdselect + 1, &fs, NULL, NULL, &to); + if (rt > 0) { - strncpy(value, where, sizeof(value) - 1); + len = recv(fd, (char *) srv_in, 320, 0); //seems that Skype only sends 320 bytes at time - if (!strcasecmp(value, "RECEIVED")) { - char msg_to_skype[256]; - DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s value: %s!\n", - SKYPIAX_P_LOG, message, obj, id, prop, value); + if (len == 320) { + unsigned int howmany; - //FIXME: TODO: allow authorization based on config param - sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id); - skypiax_skype_write(tech_pvt, msg_to_skype); + if (SAMPLERATE_SKYPIAX == 8000) { + /* we're downsampling from 16khz to 8khz, srv_out will contain each other sample from srv_in */ + a = 0; + for (i = 0; i < len / sizeof(short); i++) { + srv_out[a] = srv_in[i]; + i++; + a++; + } + } else if (SAMPLERATE_SKYPIAX == 16000) { + /* we're NOT downsampling, srv_out will contain ALL samples from srv_in */ + for (i = 0; i < len / sizeof(short); i++) { + srv_out[i] = srv_in[i]; + } + } else { + ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG); + } + /* if not yet done, let's store the half incoming frame */ + if (!tech_pvt->audiobuf_is_loaded) { + for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) { + tech_pvt->audiobuf[i] = srv_out[i]; + } + tech_pvt->audiobuf_is_loaded = 1; + } else { + /* we got a stored half frame, build a complete frame in totalbuf using the stored half frame and the current half frame */ + for (i = 0; i < SAMPLES_PER_FRAME / 2; i++) { + totalbuf[i] = tech_pvt->audiobuf[i]; + } + for (a = 0; a < SAMPLES_PER_FRAME / 2; a++) { + totalbuf[i] = srv_out[a]; + i++; + } + /* send the complete frame through the pipe to our code waiting for incoming audio */ + howmany = + skypiax_pipe_write(tech_pvt->audiopipe[1], totalbuf, + SAMPLES_PER_FRAME * sizeof(short)); + if (howmany != SAMPLES_PER_FRAME * sizeof(short)) { + ERRORA("howmany is %d, but was expected to be %d\n", SKYPIAX_P_LOG, howmany, + SAMPLES_PER_FRAME * sizeof(short)); + } + /* done with the stored half frame */ + tech_pvt->audiobuf_is_loaded = 0; } - } else if (!strcasecmp(prop, "BODY")) { - char msg_to_skype[256]; - - DEBUGA_SKYPE("Skype MSG: message: %s, obj: %s, id: %s, prop: %s!\n", - SKYPIAX_P_LOG, message, obj, id, prop); - //FIXME: TODO: on config param ??? - sprintf(msg_to_skype, "SET MESSAGE %s SEEN", id); - skypiax_skype_write(tech_pvt, msg_to_skype); + } else if (len == 0) { + DEBUGA_SKYPE("Skype incoming audio GONE\n", SKYPIAX_P_LOG); + skypiax_sleep(1000); + } else { + ERRORA("len=%d\n", SKYPIAX_P_LOG, len); + exit = 1; + break; } + } else { + if (rt) + ERRORA("SRV rt=%d\n", SKYPIAX_P_LOG, rt); + skypiax_sleep(10000); } - if (!strcasecmp(message, "CALL")) { - - strncpy(obj, where, sizeof(obj) - 1); - - where = strsep(stringp, " "); - - strncpy(id, where, sizeof(id) - 1); - - where = strsep(stringp, " "); - - strncpy(prop, where, sizeof(prop) - 1); - - where = strsep(stringp, " "); - - strncpy(value, where, sizeof(value) - 1); - - where = strsep(stringp, " "); - - DEBUGA_SKYPE - ("Skype MSG: message: %s, obj: %s, id: %s, prop: %s, value: %s,where: %s!\n", - SKYPIAX_P_LOG, message, obj, id, prop, value, where ? where : "NULL"); - - if (!strcasecmp(prop, "PARTNER_HANDLE")) { - strncpy(tech_pvt->callid_number, value, sizeof(tech_pvt->callid_number) - 1); - DEBUGA_SKYPE - ("the skype_call %s caller PARTNER_HANDLE (tech_pvt->callid_number) is: %s\n", - SKYPIAX_P_LOG, id, tech_pvt->callid_number); - return CALLFLOW_INCOMING_RING; - } - if (!strcasecmp(prop, "PARTNER_DISPNAME")) { - snprintf(tech_pvt->callid_name, sizeof(tech_pvt->callid_name) - 1, "%s%s%s", - value, where ? " " : "", where ? where : ""); - DEBUGA_SKYPE - ("the skype_call %s caller PARTNER_DISPNAME (tech_pvt->callid_name) is: %s\n", - SKYPIAX_P_LOG, id, tech_pvt->callid_name); - } - if (!strcasecmp(prop, "CONF_ID") && !strcasecmp(value, "0")) { - DEBUGA_SKYPE("the skype_call %s is NOT a conference call\n", SKYPIAX_P_LOG, id); - if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN) - tech_pvt->interface_state = SKYPIAX_STATE_PRERING; - } - if (!strcasecmp(prop, "CONF_ID") && strcasecmp(value, "0")) { - DEBUGA_SKYPE("the skype_call %s is a conference call\n", SKYPIAX_P_LOG, id); - if (tech_pvt->interface_state == SKYPIAX_STATE_DOWN) - tech_pvt->interface_state = SKYPIAX_STATE_PRERING; - } + } - if (!strcasecmp(prop, "DTMF")) { + /* let's send some frame in the pipes, so both tcp_cli and tcp_srv will have an occasion to die */ + kill_cli_size = SAMPLES_PER_FRAME * sizeof(short); + len = skypiax_pipe_write(tech_pvt->audiopipe[1], kill_cli_buff, kill_cli_size); + kill_cli_size = SAMPLES_PER_FRAME * sizeof(short); + len = skypiax_pipe_write(tech_pvt->audioskypepipe[1], kill_cli_buff, kill_cli_size); + tech_pvt->interface_state = SKYPIAX_STATE_DOWN; + kill_cli_size = SAMPLES_PER_FRAME * sizeof(short); + len = skypiax_pipe_write(tech_pvt->audiopipe[1], kill_cli_buff, kill_cli_size); + kill_cli_size = SAMPLES_PER_FRAME * sizeof(short); + len = skypiax_pipe_write(tech_pvt->audioskypepipe[1], kill_cli_buff, kill_cli_size); - DEBUGA_SKYPE("Call %s received a DTMF: %s\n", SKYPIAX_P_LOG, id, value); + DEBUGA_SKYPE("Skype incoming audio GONE\n", SKYPIAX_P_LOG); + skypiax_close_socket(fd); + if (exit) + break; + } - dtmf_received(tech_pvt, value); - } + DEBUGA_SKYPE("incoming audio server (I am it) GONE\n", SKYPIAX_P_LOG); + skypiax_close_socket(s); + return NULL; +} - if (!strcasecmp(prop, "FAILUREREASON")) { - DEBUGA_SKYPE - ("Skype has FAILED on skype_call %s. Let's wait for the FAILED message.\n", - SKYPIAX_P_LOG, id); - } - if (!strcasecmp(prop, "DURATION") && (!strcasecmp(value, "1"))) { - if (strcasecmp(id, tech_pvt->skype_call_id)) { - strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); - DEBUGA_SKYPE - ("We called a Skype contact and he answered us on skype_call: %s.\n", - SKYPIAX_P_LOG, id); - } - } +void *skypiax_do_tcp_cli_thread_func(void *obj) +{ + private_t *tech_pvt = obj; + int s; + struct sockaddr_in my_addr; + struct sockaddr_in remote_addr; + unsigned int got; + unsigned int len; + unsigned int i; + unsigned int a; + unsigned int fd; + short cli_out[SAMPLES_PER_FRAME * 2]; + short cli_in[SAMPLES_PER_FRAME]; +#ifdef WIN32 + int sin_size; +#else + unsigned int sin_size; +#endif /* WIN32 */ - if (!strcasecmp(prop, "STATUS")) { + memset(&my_addr, 0, sizeof(my_addr)); + my_addr.sin_family = AF_INET; + my_addr.sin_addr.s_addr = htonl(0x7f000001); /* use the localhost */ + my_addr.sin_port = htons(tech_pvt->tcp_cli_port); - if (!strcasecmp(value, "RINGING")) { - char msg_to_skype[1024]; - if (tech_pvt->interface_state != SKYPIAX_STATE_DIALING) { - /* we are not calling out */ + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + ERRORA("socket Error\n", SKYPIAX_P_LOG); + return NULL; + } - if (!strlen(tech_pvt->skype_call_id)) { //FIXME - /* we are not inside an active call */ - tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING; - tech_pvt->interface_state = SKYPIAX_STATE_RING; - /* no owner, no active call, let's answer */ - skypiax_skype_write(tech_pvt, "SET AGC OFF"); - skypiax_sleep(10000); - skypiax_skype_write(tech_pvt, "SET AEC OFF"); - skypiax_sleep(10000); - sprintf(msg_to_skype, "GET CALL %s PARTNER_DISPNAME", id); - skypiax_skype_write(tech_pvt, msg_to_skype); - skypiax_sleep(10000); - sprintf(msg_to_skype, "GET CALL %s PARTNER_HANDLE", id); - skypiax_skype_write(tech_pvt, msg_to_skype); - skypiax_sleep(10000); - sprintf(msg_to_skype, "ALTER CALL %s ANSWER", id); - skypiax_skype_write(tech_pvt, msg_to_skype); - DEBUGA_SKYPE("We answered a Skype RING on skype_call %s\n", SKYPIAX_P_LOG, - id); - strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); - } else { - /* we're owned, we're in a call, let's refuse */ - sprintf(msg_to_skype, "ALTER CALL %s END HANGUP", id); - skypiax_skype_write(tech_pvt, msg_to_skype); - skypiax_sleep(10000); - DEBUGA_SKYPE - ("We have NOT answered a Skype RING on skype_call %s, because we are already in a skypiax call\n", - SKYPIAX_P_LOG, id); + if (bind(s, (struct sockaddr *) &my_addr, sizeof(struct sockaddr)) < 0) { + ERRORA("bind Error\n", SKYPIAX_P_LOG); + skypiax_close_socket(s); + return NULL; + } + DEBUGA_SKYPE("started tcp_cli_thread thread.\n", SKYPIAX_P_LOG); - } - } else { - /* we are calling out */ - tech_pvt->skype_callflow = CALLFLOW_STATUS_RINGING; - tech_pvt->interface_state = SKYPIAX_STATE_RINGING; - //FIXME ast_queue_control(tech_pvt->owner, SKYPIAX_CONTROL_RINGING); - strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); - DEBUGA_SKYPE("Our remote party in skype_call %s is RINGING\n", - SKYPIAX_P_LOG, id); - } - } else if (!strcasecmp(value, "EARLYMEDIA")) { - tech_pvt->skype_callflow = CALLFLOW_STATUS_EARLYMEDIA; - tech_pvt->interface_state = SKYPIAX_STATE_DIALING; - //FIXME ast_queue_control(tech_pvt->owner, SKYPIAX_CONTROL_RINGING); - DEBUGA_SKYPE("Our remote party in skype_call %s is EARLYMEDIA\n", - SKYPIAX_P_LOG, id); - } else if (!strcasecmp(value, "MISSED")) { - DEBUGA_SKYPE("We missed skype_call %s\n", SKYPIAX_P_LOG, id); + listen(s, 6); - } else if (!strcasecmp(value, "FINISHED")) { - //tech_pvt->skype_callflow = CALLFLOW_STATUS_FINISHED; - DEBUGA_SKYPE("skype_call %s now is DOWN\n", SKYPIAX_P_LOG, id); - tech_pvt->skype_call_id[0] = '\0'; + sin_size = sizeof(remote_addr); + while ((fd = accept(s, (struct sockaddr *) &remote_addr, &sin_size)) > 0) { + DEBUGA_SKYPE("ACCEPTED\n", SKYPIAX_P_LOG); + if (!running) + break; + while (tech_pvt->interface_state != SKYPIAX_STATE_DOWN + && (tech_pvt->skype_callflow == CALLFLOW_STATUS_INPROGRESS + || tech_pvt->skype_callflow == SKYPIAX_STATE_UP)) { + unsigned int fdselect; + int rt; + fd_set fs; + struct timeval to; - if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) { - //tech_pvt->interface_state = SKYPIAX_STATE_DOWN; - return CALLFLOW_INCOMING_HANGUP; - } else { - tech_pvt->interface_state = SKYPIAX_STATE_DOWN; - } + if (!running) + break; + fdselect = fd; + FD_ZERO(&fs); + FD_SET(fdselect, &fs); + to.tv_usec = 2000000; //2000 msec + to.tv_sec = 0; - } else if (!strcasecmp(value, "CANCELLED")) { - tech_pvt->skype_callflow = CALLFLOW_STATUS_CANCELLED; - DEBUGA_SKYPE - ("we tried to call Skype on skype_call %s and Skype has now CANCELLED\n", - SKYPIAX_P_LOG, id); - tech_pvt->skype_call_id[0] = '\0'; + rt = select(fdselect + 1, NULL, &fs, NULL, &to); - if (tech_pvt->interface_state != SKYPIAX_STATE_HANGUP_REQUESTED) { - tech_pvt->interface_state = SKYPIAX_STATE_DOWN; - return CALLFLOW_INCOMING_HANGUP; - } else { - tech_pvt->interface_state = SKYPIAX_STATE_DOWN; - } - } else if (!strcasecmp(value, "FAILED")) { - tech_pvt->skype_callflow = CALLFLOW_STATUS_FAILED; - DEBUGA_SKYPE - ("we tried to call Skype on skype_call %s and Skype has now FAILED\n", - SKYPIAX_P_LOG, id); - tech_pvt->skype_call_id[0] = '\0'; - strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); - tech_pvt->interface_state = SKYPIAX_STATE_DOWN; - return CALLFLOW_INCOMING_HANGUP; - } else if (!strcasecmp(value, "REFUSED")) { - if (!strcasecmp(id, tech_pvt->skype_call_id)) { - /* this is the id of the call we are in, probably we generated it */ - tech_pvt->skype_callflow = CALLFLOW_STATUS_REFUSED; - DEBUGA_SKYPE - ("we tried to call Skype on skype_call %s and Skype has now REFUSED\n", - SKYPIAX_P_LOG, id); - strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); - tech_pvt->interface_state = SKYPIAX_STATE_DOWN; - tech_pvt->skype_call_id[0] = '\0'; - return CALLFLOW_INCOMING_HANGUP; - } else { - /* we're here because were us that refused an incoming call */ - DEBUGA_SKYPE("we REFUSED skype_call %s\n", SKYPIAX_P_LOG, id); + if (rt > 0) { - } - } else if (!strcasecmp(value, "ROUTING")) { - tech_pvt->skype_callflow = CALLFLOW_STATUS_ROUTING; - tech_pvt->interface_state = SKYPIAX_STATE_DIALING; - strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); - DEBUGA_SKYPE("skype_call: %s is now ROUTING\n", SKYPIAX_P_LOG, id); - } else if (!strcasecmp(value, "UNPLACED")) { - tech_pvt->skype_callflow = CALLFLOW_STATUS_UNPLACED; - tech_pvt->interface_state = SKYPIAX_STATE_DIALING; - strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); - DEBUGA_SKYPE("skype_call: %s is now UNPLACED\n", SKYPIAX_P_LOG, id); - } else if (!strcasecmp(value, "INPROGRESS")) { - char msg_to_skype[1024]; - tech_pvt->skype_callflow = CALLFLOW_STATUS_INPROGRESS; - strncpy(tech_pvt->skype_call_id, id, sizeof(tech_pvt->skype_call_id) - 1); - tech_pvt->interface_state = SKYPIAX_STATE_UP; - DEBUGA_SKYPE("skype_call: %s is now active\n", SKYPIAX_P_LOG, id); - sprintf(msg_to_skype, "ALTER CALL %s SET_INPUT PORT=\"%d\"", id, - tech_pvt->tcp_cli_port); - skypiax_skype_write(tech_pvt, msg_to_skype); - start_audio_threads(tech_pvt); - sprintf(msg_to_skype, "ALTER CALL %s SET_OUTPUT PORT=\"%d\"", id, - tech_pvt->tcp_srv_port); - skypiax_skype_write(tech_pvt, msg_to_skype); + /* read from the pipe the audio frame we are supposed to send out */ + got = + skypiax_pipe_read(tech_pvt->audioskypepipe[0], cli_in, + SAMPLES_PER_FRAME * sizeof(short)); + if (got != SAMPLES_PER_FRAME * sizeof(short)) { + WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, + SAMPLES_PER_FRAME * sizeof(short)); + } - tech_pvt->skype_callflow = SKYPIAX_STATE_UP; + if (got == SAMPLES_PER_FRAME * sizeof(short)) { + if (SAMPLERATE_SKYPIAX == 8000) { - if (!strlen(tech_pvt->session_uuid_str)) { - DEBUGA_SKYPE("New Inbound Channel!\n", SKYPIAX_P_LOG); - new_inbound_channel(tech_pvt); - } else { - DEBUGA_SKYPE("Outbound Channel Answered!\n", SKYPIAX_P_LOG); - outbound_channel_answered(tech_pvt); + /* we're upsampling from 8khz to 16khz, cli_out will contain two times each sample from cli_in */ + a = 0; + for (i = 0; i < got / sizeof(short); i++) { + cli_out[a] = cli_in[i]; + a++; + cli_out[a] = cli_in[i]; + a++; + } + got = got * 2; + } else if (SAMPLERATE_SKYPIAX == 16000) { + /* we're NOT upsampling, cli_out will contain just ALL samples from cli_in */ + for (i = 0; i < got / sizeof(short); i++) { + cli_out[i] = cli_in[i]; } - } else { - WARNINGA("skype_call: %s, STATUS: %s is not recognized\n", SKYPIAX_P_LOG, id, - value); + ERRORA("SAMPLERATE_SKYPIAX can only be 8000 or 16000\n", SKYPIAX_P_LOG); + } + /* send the 16khz frame to the Skype client waiting for incoming audio */ + len = send(fd, (char *) cli_out, got, 0); + + if (len == -1) { + break; + } else if (len != got) { + ERRORA("len=%d\n", SKYPIAX_P_LOG, len); + skypiax_sleep(1000); + break; } - } //STATUS - } //CALL + } else { - /* the "numbered" messages that follows are used by the directory application, not yet ported */ - if (!strcasecmp(message, "#333")) { - /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[11]: %s\n", SKYPIAX_P_LOG, - * message_2, &message_2[11]); */ - memset(tech_pvt->skype_friends, 0, 4096); - strncpy(tech_pvt->skype_friends, &message_2[11], 4095); - } - if (!strcasecmp(message, "#222")) { - /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG, - * message_2, &message_2[10]); */ - memset(tech_pvt->skype_fullname, 0, 512); - strncpy(tech_pvt->skype_fullname, &message_2[10], 511); - } - if (!strcasecmp(message, "#765")) { - /* DEBUGA_SKYPE("Skype MSG: message_2: %s, message2[10]: %s\n", SKYPIAX_P_LOG, - * message_2, &message_2[10]); */ - memset(tech_pvt->skype_displayname, 0, 512); - strncpy(tech_pvt->skype_displayname, &message_2[10], 511); + WARNINGA("got is %d, but was expected to be %d\n", SKYPIAX_P_LOG, got, + SAMPLES_PER_FRAME * sizeof(short)); + } + } else { + if (rt) + ERRORA("CLI rt=%d\n", SKYPIAX_P_LOG, rt); + skypiax_sleep(10000); } - a = 0; - } //message end - } //read_from_pipe + } + DEBUGA_SKYPE("Skype outbound audio GONE\n", SKYPIAX_P_LOG); + skypiax_close_socket(fd); + break; + } - return 0; + DEBUGA_SKYPE("outbound audio server (I am it) GONE\n", SKYPIAX_P_LOG); + skypiax_close_socket(s); + return NULL; +} + +int skypiax_skypeaudio_read(private_t * tech_pvt) +{ + unsigned int samples; + + samples = + skypiax_pipe_read(tech_pvt->audiopipe[0], tech_pvt->read_frame.data, + SAMPLES_PER_FRAME * sizeof(short)); + + if (samples != SAMPLES_PER_FRAME * sizeof(short)) { + if (samples) + WARNINGA("read samples=%u expected=%u\n", SKYPIAX_P_LOG, samples, + SAMPLES_PER_FRAME * sizeof(short)); + return 0; + } else { + /* A real frame */ + tech_pvt->read_frame.datalen = samples; + } + return 1; } int skypiax_skype_senddigit(private_t * tech_pvt, char digit) @@ -722,9 +663,7 @@ char msg_to_skype[1024]; DEBUGA_SKYPE("DIGIT received: %c\n", SKYPIAX_P_LOG, digit); - sprintf(msg_to_skype, "SET CALL %s DTMF %c", tech_pvt->skype_call_id, digit); - skypiax_skype_write(tech_pvt, msg_to_skype); return 0; @@ -743,7 +682,6 @@ sprintf(msg_to_skype, "CALL %s", rdest); if (skypiax_skype_write(tech_pvt, msg_to_skype) < 0) { - ERRORA("failed to communicate with Skype client, now exit\n", SKYPIAX_P_LOG); return -1; }