/* Copyright 2015 Kuklin István This file is part of OpenSIPphone. OpenSIPphone is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License. OpenSIPphone is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenSIPphone. If not, see . */ #include #include #include #include #include #include #include #include /* superset of previous */ #include #include "gtk_ui.h" #include "gtk_uconf.h" #include "main.h" #include "sip.h" #include "gtk_debug.h" #include "sound.h" #include "rtp.h" char vm_number[100]; void osp_call_number(GtkTreeViewColumn *null, gpointer data) { char *number = (char *)(data); osp_print(number, GTK_TEXT_VIEW(debug_view)); gtk_entry_set_text(GTK_ENTRY(dial_entry), number); osp_make_call(); } int init_osp_eXosip() { strcpy(vm_number, ""); if(eXosip_init_done == 1)eXosip_quit(ctx); eXosip_init_done = 1; TRACE_INITIALIZE (6, NULL); ctx = eXosip_malloc(); if (ctx == NULL) { printf("sip.c: ctx is null, dying\n"); return -1; } j = eXosip_init(ctx); if(j != 0) { printf("sip.c: failed to initialize eXoSIP context, dying"); return -1; } printf("eXoSIP main initializing is done\n"); int val=1; j = eXosip_set_option (ctx, EXOSIP_OPT_SET_TLS_VERIFY_CERTIFICATE, (void*)&val); eXosip_tls_ctx_t tls_info; switch (user_settings.transport){ case 0: j = eXosip_listen_addr(ctx, IPPROTO_UDP, NULL, 5060, AF_INET, 0); break; case 1: j = eXosip_listen_addr(ctx, IPPROTO_TCP, NULL, 5060, AF_INET, 0); break; case 2: j = eXosip_listen_addr (ctx, IPPROTO_TCP, NULL, 5061, AF_INET, 1); //FAIL if(j != 0 ) { printf("eXoSIP: cannot listen, returning\n"); return -1; } memset(&tls_info, 0, sizeof(eXosip_tls_ctx_t)); snprintf(tls_info.root_ca_cert, sizeof(tls_info.root_ca_cert), "/etc/ssl/certs/ca-certificates.crt"); j = 0; j = eXosip_set_option (ctx, EXOSIP_OPT_SET_TLS_CERTIFICATES_INFO, (void*)&tls_info); if(j < 0) printf("ERROR INITIALIZING TLS TRANSPORT!\n"); else printf("TLS TRANSPORT INITIALIZED\nCA file: %s\n", tls_info.root_ca_cert); break; default: j = eXosip_listen_addr(ctx, IPPROTO_UDP, NULL, 0, AF_INET, 0); } eXosip_set_user_agent (ctx, selfname); val=17000; eXosip_set_option (ctx, EXOSIP_OPT_UDP_KEEP_ALIVE, (void*)&val); val=2; eXosip_set_option (ctx, EXOSIP_OPT_DNS_CAPABILITIES, (void*)&val); val=1; eXosip_set_option (ctx, EXOSIP_OPT_USE_RPORT, (void*)&val); val=26; eXosip_set_option (ctx, EXOSIP_OPT_SET_DSCP, (void*)&val); eXosip_set_option (ctx, EXOSIP_OPT_SET_IPV4_FOR_GATEWAY, (void *)gtk_entry_get_text(GTK_ENTRY(domain_entry))); val=0; eXosip_set_option (ctx, EXOSIP_OPT_DNS_CAPABILITIES, &val); reg = NULL; char reg_uri[300]; char prov_uri[200]; strcpy(prov_uri, "sip:"); strcat(prov_uri, (char *)gtk_entry_get_text(GTK_ENTRY(domain_entry))); strcpy(reg_uri, "sip:"); strcat(reg_uri, (char *)gtk_entry_get_text(GTK_ENTRY(username_entry))); strcat(reg_uri, "@"); strcat(reg_uri, (char *)gtk_entry_get_text(GTK_ENTRY(domain_entry))); printf("Registration URI: %s\nProvider URI: %s\n", reg_uri, prov_uri); eXosip_lock(ctx); rid = eXosip_register_build_initial_register (ctx, reg_uri, prov_uri, NULL, 1800, ®); if(rid < 0) { printf("Returned -1 as asked.\n"); eXosip_unlock (ctx); return -1; } osip_message_set_supported (reg, "100rel"); osip_message_set_supported (reg, "path"); j = eXosip_register_send_register (ctx, rid, reg); eXosip_add_authentication_info (ctx, (char *)gtk_entry_get_text(GTK_ENTRY(username_entry)), (char *)gtk_entry_get_text(GTK_ENTRY(username_entry)), (char *)gtk_entry_get_text(GTK_ENTRY(password_entry)), NULL, NULL); eXosip_unlock (ctx); pthread_cancel(event_pth); pthread_create(&event_pth, NULL, osp_event_listen, NULL); return 0; } void *osp_event_listen() { //Listening for events... //eXosip_event_t *evt; int first_time_reg_failure = 1; for (;;) { evt = eXosip_event_wait (ctx, 0, 50); eXosip_lock(ctx); eXosip_automatic_action (ctx); eXosip_unlock(ctx); if (evt == NULL) continue; if(evt->type == EXOSIP_REGISTRATION_SUCCESS ) { osp_print("Registered successfully.\n", GTK_TEXT_VIEW(user_message_view)); gdk_threads_add_idle((GSourceFunc)(on_sip_registration_done), GINT_TO_POINTER(1)); } if(evt->type == EXOSIP_REGISTRATION_FAILURE ) { if(first_time_reg_failure == 1 && user_settings.transport == 2) first_time_reg_failure = 0; else osp_print("Failed to register.\n", GTK_TEXT_VIEW(user_message_view)); gdk_threads_add_idle((GSourceFunc)(on_sip_registration_done), GINT_TO_POINTER(0)); } if(evt->type == EXOSIP_CALL_RINGING) { on_the_phone = TRUE; did = evt->did; cid = evt->cid; tid = evt->tid; gdk_threads_add_idle(after_trying, NULL); osp_print("Ringing...\n", GTK_TEXT_VIEW(user_message_view)); } if(evt->type == EXOSIP_CALL_ANSWERED) { on_the_phone = TRUE; did = evt->did; cid = evt->cid; tid = evt->tid; pthread_cancel(rst); gdk_threads_add_idle(on_call_answered, NULL); { osip_message_t *ack; j = eXosip_call_build_ack(ctx, did, &ack); if(j == 0) { osp_print("Sending ACK\n", GTK_TEXT_VIEW(debug_view)); eXosip_call_send_ack(ctx, did, ack); } } osp_on_call_established(); } if(evt->type == EXOSIP_CALL_GLOBALFAILURE || evt->type == EXOSIP_CALL_REQUESTFAILURE || evt->type == EXOSIP_CALL_SERVERFAILURE || evt->type == EXOSIP_CALL_GLOBALFAILURE){ char text_buffer[300]; osp_print("MAIN: SOME KIND OF FAILURE EVENT CAUGHT\n", GTK_TEXT_VIEW(debug_view)); if(evt->response->status_code != 401) { sprintf(text_buffer, "SIP %d %s\n", evt->response->status_code, evt->response->reason_phrase); if(evt->response->status_code = 404) reset_dial_interface(); osp_print(text_buffer, GTK_TEXT_VIEW(user_message_view)); } } if(evt->type == EXOSIP_CALL_CLOSED || evt->type == EXOSIP_CALL_REQUESTFAILURE || evt->type == EXOSIP_CALL_CANCELLED) { if(did == evt->did) reset_dial_interface(); gdk_threads_add_idle(close_notification, incoming_call_notification); pthread_cancel(rst); pthread_cancel(osp_rtp_play_thread); }; if(evt->type == EXOSIP_CALL_CLOSED) { gdk_threads_add_idle(dial_entry_empty, NULL); osp_print("Call ended\n", GTK_TEXT_VIEW(user_message_view)); } if(evt->type == EXOSIP_CALL_INVITE) { if(on_the_phone == FALSE) { did = evt->did; cid = evt->cid; tid = evt->tid; eXosip_lock (ctx); eXosip_call_send_answer (ctx, evt->tid, 180, NULL); eXosip_unlock (ctx); char dest[4096]; osip_uri_t *uri = osip_from_get_url(evt->request->from); sprintf(dest, "address@hidden", osip_uri_get_username(uri), osip_uri_get_host(uri)); gdk_threads_add_idle(on_incoming_call, dest); osp_print("MAIN: INVITE EVENT CAUGHT\n", GTK_TEXT_VIEW(debug_view)); struct osp_play_audio_file_options_t options; strcpy(options.path, gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(ringtone_chooser))); if(0 != pthread_create(&rst, NULL, (void * (*)(void *))(osp_play_audio_file), (&options))) { osp_print("Error creating sound thread!\n", GTK_TEXT_VIEW(debug_view)); }; //osp_play_audio_file("/usr/share/sounds/ubuntu/stereo/desktop-login.ogg"); } else { eXosip_lock (ctx); eXosip_call_terminate (ctx, evt->cid, evt->did); eXosip_unlock (ctx); }; } if(evt->type == EXOSIP_MESSAGE_NEW || evt->type == EXOSIP_MESSAGE_PROCEEDING ) { osp_print("MAIN: MESSAGE EVENT CAUGHT\n", GTK_TEXT_VIEW(debug_view)); char text_buffer[300]; sprintf(text_buffer, "Request method is: %s\n", evt->request->sip_method); //MWI if(strcmp("NOTIFY", evt->request->sip_method) == 0) { //char *req_uri_str = osip_url_to_str(evt->request->req_uri); { osip_body_t *body = osip_list_get(&(evt->request->bodies), 0); char *dest=NULL; size_t length=0; osip_body_to_str(body, &dest, &length); osp_print(dest, GTK_TEXT_VIEW(debug_view)); if(strstr(dest, "Messages-Waiting: yes") != NULL) { osp_print("New voicemail.\n", GTK_TEXT_VIEW(debug_view)); gdk_threads_add_idle(mwi_notify, GINT_TO_POINTER(TRUE)); } else if(strstr(dest, "Messages-Waiting: no") != NULL) { osp_print("No voicemail.\n", GTK_TEXT_VIEW(debug_view)); gdk_threads_add_idle(mwi_notify, GINT_TO_POINTER(FALSE)); } char *dig_vm_number = dig_vm_number = strstr(dest, "sip:"); if(dig_vm_number == NULL) osp_print("No voicemail account.\n", GTK_TEXT_VIEW(debug_view)); sscanf(dig_vm_number, "%s\n", vm_number); { char output_buffer[1024]; sprintf(output_buffer, "Voicemail number is: %s\n", vm_number); osp_print(output_buffer, GTK_TEXT_VIEW(debug_view)); } } } osp_print(text_buffer, GTK_TEXT_VIEW(debug_view)); if(strcmp(evt->request->sip_method, "OPTIONS") == 0) { eXosip_lock (ctx); j = 0; j = eXosip_options_build_answer(ctx, evt->tid, 200, &msg); if(j < 0) osp_print("There was a problem building the options answer.\n", GTK_TEXT_VIEW(debug_view)); j = eXosip_options_send_answer(ctx, evt->tid, 200, msg); if(j < 0) osp_print("There was a problem sending the options answer.\n", GTK_TEXT_VIEW(debug_view)); eXosip_unlock (ctx); } if((strcmp(evt->request->sip_method, "BYE") == 0 || strcmp(evt->request->sip_method, "CANCEL") == 0)) { on_the_phone = FALSE; gdk_threads_add_idle(enable_dial_interface, GINT_TO_POINTER(1)); } } eXosip_event_free(evt); } return NULL; } void osp_sip_quit() { eXosip_lock (ctx); j = eXosip_register_build_register (ctx, rid, 0, ®); if (j < 0) { eXosip_unlock (ctx); return; } eXosip_register_send_register (ctx, rid, reg); eXosip_unlock (ctx); } void osp_sdp_build (osip_message_t *invite) { char tmp[4096]; char tmp2[300]; char localip[128]; char port_str[6]; sprintf(port_str, "49170"); eXosip_guess_localip (ctx, AF_INET, localip, 128); sprintf(tmp, "v=0\r\no=%s 0 0 IN IP4 %s\r\ns=conversation\r\nc=IN IP4 %s\r\n", gtk_entry_get_text (GTK_ENTRY (username_entry)), localip, localip); if(user_settings.srtp_enabled == TRUE) sprintf(tmp + strlen(tmp), "t=0 0\r\nm=audio %s RTP/SAVP 0 8 101\r\n", port_str); else sprintf(tmp + strlen(tmp), "t=0 0\r\nm=audio %s RTP/AVP 0 8 101\r\n", port_str); sprintf(tmp + strlen(tmp), "a=sendrecv\r\n"); //Codecs here... sprintf(tmp + strlen(tmp), "a=rtpmap:0 PCMU/8000\r\n"); //sprintf(tmp + strlen(tmp), "a=rtpmap:8 PCMA/8000\r\n"); //SRTP key if(user_settings.srtp_enabled == TRUE) sprintf(tmp+strlen(tmp), "a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj\r\n"); osip_message_set_body (invite, tmp, strlen (tmp)); osip_message_set_content_type (invite, "application/sdp"); } void osp_make_call() { osip_message_t *invite; char from[300]; char to[300]; strcpy(from, "sip:"); osp_print(from, GTK_TEXT_VIEW(debug_view)); strcat(from, gtk_entry_get_text (GTK_ENTRY (username_entry) ) ); strcat(from, "@"); strcat(from, gtk_entry_get_text (GTK_ENTRY (domain_entry) ) ); strcpy(to, ""); if(strstr(gtk_entry_get_text(GTK_ENTRY(dial_entry)), "sip:") == NULL) strcat(to, "sip:"); strcat(to, gtk_entry_get_text (GTK_ENTRY (dial_entry) ) ); if(strstr(gtk_entry_get_text(GTK_ENTRY(dial_entry)), "@") == NULL) { strcat(to, "@"); strcat(to, gtk_entry_get_text (GTK_ENTRY (domain_entry) ) ); } gtk_entry_set_text(GTK_ENTRY(dial_entry), to); j = eXosip_call_build_initial_invite (ctx, &invite, (char *)(to), (char *)(from), NULL, NULL); if(user_settings.transport == 2) { osip_uri_param_add(&(invite->req_uri->url_params), osip_strdup("transport"), osip_strdup("TLS")); }; { char output_buffer[DEBUG_MESSAGE_DATA_LENGTH]; char *uri_buffer; osip_uri_to_str(osip_message_get_uri(invite), &uri_buffer); sprintf(output_buffer, "Connecting to:\n%s\n", uri_buffer); osp_print(output_buffer, GTK_TEXT_VIEW(user_message_view)); } osip_message_set_supported(invite, "100rel"); osp_sdp_build(invite); eXosip_lock (ctx); cid = eXosip_call_send_initial_invite (ctx, invite); eXosip_unlock(ctx); on_the_phone = TRUE; } void osp_reject_call() { pthread_cancel(rst); eXosip_lock (ctx); eXosip_call_terminate (ctx, cid, did); eXosip_unlock (ctx); notify_notification_close(incoming_call_notification, NULL); gdk_threads_add_idle(dial_entry_empty, NULL); osp_print("Ending call\n", GTK_TEXT_VIEW(user_message_view)); on_the_phone = FALSE; pthread_cancel(osp_rtp_play_thread); } void osp_answer_call() { pthread_cancel(rst); on_the_phone = TRUE; msg = NULL; eXosip_lock (ctx); j = eXosip_call_build_answer (ctx, tid, 200, &msg); if (j != 0) { eXosip_call_send_answer (ctx, tid, 400, NULL); } else { osp_sdp_build(msg); if (j != 0) { osip_message_free (msg); eXosip_call_send_answer (ctx, tid, 415, NULL); } else eXosip_call_send_answer (ctx, tid, 200, msg); } eXosip_unlock (ctx); osp_on_call_established(); } void osp_on_call_established() { osp_print("Call established\n", GTK_TEXT_VIEW(user_message_view)); notify_notification_close(incoming_call_notification, NULL); sdp_message_t * sdp_remote = NULL; sdp_remote = eXosip_get_remote_sdp(ctx, did); if(sdp_remote == NULL) { osp_print("Failed to get remote SDP!\n", GTK_TEXT_VIEW(debug_view)); return; } char *tempbuf = malloc(sizeof(*tempbuf)*512); char *sdpmsg = malloc(sizeof(*tempbuf)*512); char *needle = "m=audio "; sdp_message_to_str(sdp_remote, &sdpmsg); sprintf(tempbuf, "SDP: Remote body is:\n%s\n", sdpmsg); char *needle_pos = strstr(sdpmsg, needle); if(needle_pos != NULL) { int audio_port; osp_print(tempbuf, GTK_TEXT_VIEW(debug_view)); sscanf(needle_pos, "m=audio %d RTP", &audio_port); sprintf(tempbuf, "RTP audio port number is: %d\n", audio_port); osp_print(tempbuf, GTK_TEXT_VIEW(debug_view)); pthread_create(&osp_rtp_play_thread, NULL, osp_rtp_play, &audio_port); } else { osp_print("Audio port number not found!\n", GTK_TEXT_VIEW(debug_view)); } free(tempbuf); tempbuf = NULL; }