static void end_session_with_error(SESSION_INSTANCE* session_instance, const char* condition_value, const char* description) { ERROR_HANDLE error_handle = error_create(condition_value); if (error_handle == NULL) { /* fatal error */ session_set_state(session_instance, SESSION_STATE_DISCARDING); (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot allocate error handle to end session"); } else { if ((error_set_description(error_handle, description) != 0) || (send_end_frame(session_instance, error_handle) != 0)) { /* fatal error */ session_set_state(session_instance, SESSION_STATE_DISCARDING); (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot allocate error handle to end session"); } else { session_set_state(session_instance, SESSION_STATE_DISCARDING); } error_destroy(error_handle); } }
int session_end(SESSION_HANDLE session, const char* condition_value, const char* description) { int result; if (session == NULL) { result = __LINE__; } else { SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)session; if ((session_instance->session_state != SESSION_STATE_UNMAPPED) && (session_instance->session_state != SESSION_STATE_DISCARDING)) { ERROR_HANDLE error_handle = NULL; result = 0; if (condition_value != NULL) { error_handle = error_create(condition_value); if (error_handle == NULL) { result = __LINE__; } else { if (error_set_description(error_handle, description) != 0) { result = __LINE__; } } } if (result == 0) { if (send_end_frame(session_instance, error_handle) != 0) { result = __LINE__; } else { session_set_state(session_instance, SESSION_STATE_DISCARDING); result = 0; } } if (error_handle != NULL) { error_destroy(error_handle); } } else { result = 0; } } return result; }
/* * to be called by a timeout and everyone who wants to stop a running effect * to go back to STATE_READY */ gint session_effect_stop_cb(gpointer data) { session_t *session = (session_t *) data; session_set_state(session, STATE_READY); return FALSE; /* don't call me regularly */ }
static void on_connection_state_changed(void* context, CONNECTION_STATE new_connection_state, CONNECTION_STATE previous_connection_state) { SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)context; /* Codes_SRS_SESSION_01_060: [If the previous connection state is not OPENED and the new connection state is OPENED, the BEGIN frame shall be sent out and the state shall be switched to BEGIN_SENT.] */ if ((new_connection_state == CONNECTION_STATE_OPENED) && (previous_connection_state != CONNECTION_STATE_OPENED) && (session_instance->session_state == SESSION_STATE_UNMAPPED)) { if (send_begin(session_instance) == 0) { session_set_state(session_instance, SESSION_STATE_BEGIN_SENT); } } /* Codes_SRS_SESSION_01_061: [If the previous connection state is OPENED and the new connection state is not OPENED anymore, the state shall be switched to DISCARDING.] */ else if ((new_connection_state == CONNECTION_STATE_CLOSE_RCVD) || (new_connection_state == CONNECTION_STATE_END)) { session_set_state(session_instance, SESSION_STATE_DISCARDING); } }
/* * will be called directly after getting VCON from ttyI * includes state transition */ void session_start_conversation(session_t *session) { char *digits; /* time in digits form */ if (isdn_set_full_duplex(session->isdn_fd)) { /* ISDN full duplex (REC start command) error */ fprintf(stderr, "Error setting full duplex audio mode.\n"); isdn_hangup(session->isdn_fd); session_set_state(session, STATE_READY); cid_set_duration(session, _("(HW ERROR)")); } else { /* full duplex ok: audio mode */ session->vcon_time = time(NULL); /* for caller id monitor */ cid_set_date(session, session->vcon_time); session_set_state(session, STATE_CONVERSATION); if (session->option_record) { if ((digits = util_digitstime(&session->vcon_time))) { if (recording_open(session->recorder, digits, session->option_recording_format)) { fprintf(stderr, "Error opening audio file.\n"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON( session->record_checkbutton), FALSE); } free(digits); cid_row_mark_record(session, session->cid_num - 1); } else { fprintf(stderr, "Error generating audio filename.\n"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON( session->record_checkbutton), FALSE); } } if (isdn_blockmode(session->isdn_fd, 1)) /* blockmode error */ fprintf(stderr, "Warning: Switching to ISDN blockmode not successful.\n"); session_init_conversation(session); /* init some conversation variables */ session_io_handlers_stop(session); session_reset_audio(session); session_io_handlers_start(session); /* start with first block to start recording */ process_audio_source(session); } }
SESSION_HANDLE session_create(CONNECTION_HANDLE connection, ON_LINK_ATTACHED on_link_attached, void* callback_context) { SESSION_INSTANCE* result; if (connection == NULL) { /* Codes_SRS_SESSION_01_031: [If connection is NULL, session_create shall fail and return NULL.] */ result = NULL; } else { /* Codes_SRS_SESSION_01_030: [session_create shall create a new session instance and return a non-NULL handle to it.] */ result = amqpalloc_malloc(sizeof(SESSION_INSTANCE)); /* Codes_SRS_SESSION_01_042: [If allocating memory for the session fails, session_create shall fail and return NULL.] */ if (result != NULL) { result->connection = connection; result->link_endpoints = NULL; result->link_endpoint_count = 0; result->handle_max = 4294967295u; /* Codes_SRS_SESSION_01_057: [The delivery ids shall be assigned starting at 0.] */ /* Codes_SRS_SESSION_01_017: [The nextoutgoing-id MAY be initialized to an arbitrary value ] */ result->next_outgoing_id = 0; result->desired_incoming_window = 1; result->incoming_window = 1; result->outgoing_window = 1; result->handle_max = 4294967295u; result->remote_incoming_window = 0; result->remote_outgoing_window = 0; result->previous_session_state = SESSION_STATE_UNMAPPED; result->is_underlying_connection_open = 0; result->session_state = SESSION_STATE_UNMAPPED; result->on_link_attached = on_link_attached; result->on_link_attached_callback_context = callback_context; /* Codes_SRS_SESSION_01_032: [session_create shall create a new session endpoint by calling connection_create_endpoint.] */ result->endpoint = connection_create_endpoint(connection); if (result->endpoint == NULL) { /* Codes_SRS_SESSION_01_033: [If connection_create_endpoint fails, session_create shall fail and return NULL.] */ amqpalloc_free(result); result = NULL; } else { session_set_state(result, SESSION_STATE_UNMAPPED); } } } return result; }
/********************************************************************** * %FUNCTION: session_free * %ARGUMENTS: * ses -- a session to free * %RETURNS: * Nothing * %DESCRIPTION: * Frees a session, closing down all resources associated with it. ***********************************************************************/ void l2tp_session_free(l2tp_session *ses, char const *reason) { session_set_state(ses, SESSION_IDLE); DBG(l2tp_db(DBG_SESSION, "session_free(%s) %s\n", l2tp_debug_session_to_str(ses), reason)); if (ses->call_ops && ses->call_ops->close) { ses->call_ops->close(ses, reason); } memset(ses, 0, sizeof(l2tp_session)); free(ses); }
SESSION_HANDLE session_create_from_endpoint(CONNECTION_HANDLE connection, ENDPOINT_HANDLE endpoint, ON_LINK_ATTACHED on_link_attached, void* callback_context) { SESSION_INSTANCE* result; if (endpoint == NULL) { result = NULL; } else { result = amqpalloc_malloc(sizeof(SESSION_INSTANCE)); if (result != NULL) { result->connection = connection; result->link_endpoints = NULL; result->link_endpoint_count = 0; result->handle_max = 4294967295u; result->next_outgoing_id = 0; result->incoming_window = 1; result->outgoing_window = 1; result->handle_max = 4294967295u; result->remote_incoming_window = 0; result->remote_outgoing_window = 0; result->previous_session_state = SESSION_STATE_UNMAPPED; result->is_underlying_connection_open = 0; result->session_state = SESSION_STATE_UNMAPPED; result->on_link_attached = on_link_attached; result->on_link_attached_callback_context = callback_context; result->endpoint = endpoint; session_set_state(result, SESSION_STATE_UNMAPPED); } } return result; }
static void on_frame_received(void* context, AMQP_VALUE performative, uint32_t payload_size, const unsigned char* payload_bytes) { SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)context; AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative); if (is_begin_type_by_descriptor(descriptor)) { BEGIN_HANDLE begin_handle; if (amqpvalue_get_begin(performative, &begin_handle) != 0) { connection_close(session_instance->connection, "amqp:decode-error", "Cannot decode BEGIN frame"); } else { if ((begin_get_incoming_window(begin_handle, &session_instance->remote_incoming_window) != 0) || (begin_get_next_outgoing_id(begin_handle, &session_instance->next_incoming_id) != 0)) { /* error */ begin_destroy(begin_handle); session_set_state(session_instance, SESSION_STATE_DISCARDING); connection_close(session_instance->connection, "amqp:decode-error", "Cannot get incoming windows and next outgoing id"); } else { begin_destroy(begin_handle); if (session_instance->session_state == SESSION_STATE_BEGIN_SENT) { session_set_state(session_instance, SESSION_STATE_MAPPED); } else if(session_instance->session_state == SESSION_STATE_UNMAPPED) { session_set_state(session_instance, SESSION_STATE_BEGIN_RCVD); if (send_begin(session_instance) != 0) { connection_close(session_instance->connection, "amqp:internal-error", "Failed sending BEGIN frame"); session_set_state(session_instance, SESSION_STATE_DISCARDING); } else { session_set_state(session_instance, SESSION_STATE_MAPPED); } } } } } else if (is_attach_type_by_descriptor(descriptor)) { const char* name = NULL; ATTACH_HANDLE attach_handle; if (amqpvalue_get_attach(performative, &attach_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode ATTACH frame"); } else { role role; AMQP_VALUE source; AMQP_VALUE target; if ((attach_get_name(attach_handle, &name) != 0) || (attach_get_role(attach_handle, &role) != 0) || (attach_get_source(attach_handle, &source) != 0) || (attach_get_target(attach_handle, &target) != 0)) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot get link name from ATTACH frame"); } else { LINK_ENDPOINT_INSTANCE* link_endpoint = find_link_endpoint_by_name(session_instance, name); if (link_endpoint == NULL) { /* new link attach */ if (session_instance->on_link_attached != NULL) { LINK_ENDPOINT_HANDLE new_link_endpoint = session_create_link_endpoint(session_instance, name); if (new_link_endpoint == NULL) { end_session_with_error(session_instance, "amqp:internal-error", "Cannot create link endpoint"); } else { if (!session_instance->on_link_attached(session_instance->on_link_attached_callback_context, new_link_endpoint, name, role, source, target)) { session_destroy_link_endpoint(new_link_endpoint); new_link_endpoint = NULL; } else { if (new_link_endpoint->frame_received_callback != NULL) { new_link_endpoint->frame_received_callback(new_link_endpoint->callback_context, performative, payload_size, payload_bytes); } } } } } else { if (attach_get_handle(attach_handle, &link_endpoint->input_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot get input handle from ATTACH frame"); } else { link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes); } } } attach_destroy(attach_handle); } } else if (is_detach_type_by_descriptor(descriptor)) { DETACH_HANDLE detach_handle; if (amqpvalue_get_detach(performative, &detach_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode DETACH frame"); } else { uint32_t remote_handle; if (detach_get_handle(detach_handle, &remote_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot get handle from DETACH frame"); detach_destroy(detach_handle); } else { detach_destroy(detach_handle); LINK_ENDPOINT_INSTANCE* link_endpoint = find_link_endpoint_by_input_handle(session_instance, remote_handle); if (link_endpoint == NULL) { end_session_with_error(session_instance, "amqp:session:unattached-handle", ""); } else { link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes); } } } } else if (is_flow_type_by_descriptor(descriptor)) { FLOW_HANDLE flow_handle; if (amqpvalue_get_flow(performative, &flow_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode FLOW frame"); } else { uint32_t remote_handle; transfer_number flow_next_incoming_id; uint32_t flow_incoming_window; if ((flow_get_next_outgoing_id(flow_handle, &session_instance->next_incoming_id) != 0) || (flow_get_next_incoming_id(flow_handle, &flow_next_incoming_id) != 0) || (flow_get_incoming_window(flow_handle, &flow_incoming_window) != 0)) { flow_destroy(flow_handle); end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode FLOW frame"); } else { LINK_ENDPOINT_INSTANCE* link_endpoint_instance = NULL; session_instance->remote_incoming_window = flow_next_incoming_id + flow_incoming_window - session_instance->next_outgoing_id; if (flow_get_handle(flow_handle, &remote_handle) == 0) { link_endpoint_instance = find_link_endpoint_by_input_handle(session_instance, remote_handle); } flow_destroy(flow_handle); if (link_endpoint_instance != NULL) { link_endpoint_instance->frame_received_callback(link_endpoint_instance->callback_context, performative, payload_size, payload_bytes); } size_t i = 0; while ((session_instance->remote_incoming_window > 0) && (i < session_instance->link_endpoint_count)) { /* notify the caller that it can send here */ if (session_instance->link_endpoints[i]->on_session_flow_on != NULL) { session_instance->link_endpoints[i]->on_session_flow_on(session_instance->link_endpoints[i]->callback_context); } i++; } } } } else if (is_transfer_type_by_descriptor(descriptor)) { TRANSFER_HANDLE transfer_handle; if (amqpvalue_get_transfer(performative, &transfer_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode TRANSFER frame"); } else { uint32_t remote_handle; delivery_number delivery_id; transfer_get_delivery_id(transfer_handle, &delivery_id); if (transfer_get_handle(transfer_handle, &remote_handle) != 0) { transfer_destroy(transfer_handle); end_session_with_error(session_instance, "amqp:decode-error", "Cannot get handle from TRANSFER frame"); } else { transfer_destroy(transfer_handle); session_instance->next_incoming_id++; session_instance->remote_outgoing_window--; session_instance->incoming_window--; LINK_ENDPOINT_INSTANCE* link_endpoint = find_link_endpoint_by_output_handle(session_instance, remote_handle); if (link_endpoint == NULL) { end_session_with_error(session_instance, "amqp:session:unattached-handle", ""); } else { link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes); } if (session_instance->incoming_window == 0) { session_instance->incoming_window = session_instance->desired_incoming_window; send_flow(session_instance); } } } } else if (is_disposition_type_by_descriptor(descriptor)) { uint32_t i; for (i = 0; i < session_instance->link_endpoint_count; i++) { LINK_ENDPOINT_INSTANCE* link_endpoint = session_instance->link_endpoints[i]; link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes); } } else if (is_end_type_by_descriptor(descriptor)) { END_HANDLE end_handle; if (amqpvalue_get_end(performative, &end_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode END frame"); } else { if ((session_instance->session_state != SESSION_STATE_END_RCVD) && (session_instance->session_state != SESSION_STATE_DISCARDING)) { session_set_state(session_instance, SESSION_STATE_END_RCVD); if (send_end_frame(session_instance, NULL) != 0) { /* fatal error */ (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot send END frame."); } session_set_state(session_instance, SESSION_STATE_DISCARDING); } } } }
/* * Load all settings from widgets into session * -> used by gtksettings_cb_ok and gtksettings_cb_save * * input: widget: the widget with associated data widgets and session inside * * returns 0 on success, -1 otherwise (bad audio settings) */ static int gtksettings_try(GtkWidget *widget) { session_t *session = gtk_object_get_data(GTK_OBJECT(widget), "session"); /* save current settings */ char *old_msn = session->msn; char *old_msns = session->msns; int successful = 1; GtkWidget *entry; GtkWidget *button; GSList *list; /* exec_on_incoming */ entry = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "exec_on_incoming_entry"); if (entry) { free(session->exec_on_incoming); session->exec_on_incoming = strdup(gtk_entry_get_text(GTK_ENTRY(entry))); } else fprintf(stderr, "gtksettings_cb_ok: Error getting exec_on_incoming.\n"); /* popup checkbutton */ button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "popup_checkbutton"); if (button) session->option_popup = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); else fprintf(stderr, "gtksettings_cb_ok: Error getting popup state.\n"); /* recording_format */ list = (GSList *) gtk_object_get_data(GTK_OBJECT(widget), "recording_format"); if (list) { while (list) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(list->data))) { session->option_recording_format = (enum recording_format_t) gtk_object_get_data(GTK_OBJECT(list->data), "rec_format"); } list = list->next; } } else fprintf(stderr, "gtksettings_cb_ok: Error getting recording_format.\n"); /* msn */ entry = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "msn_entry"); if (entry) session->msn = strdup(gtk_entry_get_text(GTK_ENTRY(entry))); else fprintf(stderr, "gtksettings_cb_ok: Error getting msn.\n"); /* msns */ entry = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "msns_entry"); if (entry) session->msns = strdup(gtk_entry_get_text(GTK_ENTRY(entry))); else fprintf(stderr, "gtksettings_cb_ok: Error getting msns.\n"); /* history_entry */ entry = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "history_entry"); if (entry) session->dial_number_history_maxlen = strtol(gtk_entry_get_text(GTK_ENTRY(entry)), NULL, 0); else fprintf(stderr, "gtksettings_cb_ok: Error getting history.\n"); session->dial_number_history_pointer = 0; /* cid_max_entry */ entry = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "cid_max_entry"); if (entry) session->cid_num_max = strtol(gtk_entry_get_text(GTK_ENTRY(entry)), NULL, 0); else fprintf(stderr, "gtksettings_cb_ok: " "Error getting caller id maximum rows.\n"); /* cid_calls_merge_checkbutton */ button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "cid_calls_merge_checkbutton"); if (button) session->option_calls_merge = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); else fprintf(stderr, "gtksettings_cb_ok: Error getting isdnlog calls_merge state.\n"); /* cid_calls_merge_max_entry */ entry = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "cid_calls_merge_max_entry"); if (entry) session->option_calls_merge_max_days = strtol(gtk_entry_get_text(GTK_ENTRY(entry)), NULL, 0); else fprintf(stderr, "gtksettings_cb_ok: " "Error getting maximum number of days for isdnlog retrieval.\n"); /* save checkbutton */ button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "save_checkbutton"); if (button) session->option_save_options = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); else fprintf(stderr, "gtksettings_cb_ok: Error getting save_options state.\n"); /* * audio stop/start */ if (session->audio_device_name_in) { /* shut down if defined */ session_io_handlers_stop(session); if (!session->option_release_devices) /* audio_close if normal mode */ session_audio_deinit(session); free(session->audio_device_name_in); free(session->audio_device_name_out); } /* audio_device_name_in */ entry = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "audio_device_name_in_entry"); if (entry) session->audio_device_name_in = strdup(gtk_entry_get_text(GTK_ENTRY(entry))); else fprintf(stderr,"gtksettings_cb_ok: Error getting audio_device_name_in.\n"); /* audio_device_name_out */ entry = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "audio_device_name_out_entry"); if (entry) session->audio_device_name_out = strdup(gtk_entry_get_text(GTK_ENTRY(entry))); else fprintf(stderr, "gtksettings_cb_ok: Error getting audio_device_name_out.\n"); /* release checkbutton */ button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(widget), "release_checkbutton"); if (button) session->option_release_devices = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); else fprintf(stderr, "gtksettings_cb_ok: Error getting release_devices state.\n"); if (!session->option_release_devices) { if (session_audio_init(session)) { successful = 0; free(session->audio_device_name_in); free(session->audio_device_name_out); session->audio_device_name_in = NULL; /* flag for audio shut down */ } } if (session->audio_device_name_in) { /* OK or unknown */ session_io_handlers_start(session); session_set_state(session, STATE_READY); /* update everything */ } /* try to apply msn settings */ if (isdn_setMSN(session->isdn_fd, session->msn) || isdn_setMSNs(session->isdn_fd, session->msns)) { /* got some problem */ free(session->msn); free(session->msns); session->msn = old_msn; session->msns = old_msns; isdn_setMSN(session->isdn_fd, session->msn); isdn_setMSNs(session->isdn_fd, session->msns); successful = 0; } else { /* everything's fine */ free(old_msn); free(old_msns); } return !!successful - 1; }
/* * callback for gtk on audio isdn input * * input: data: session (session_t *) * fd: file descriptor where we got the input from * condition: will be GDK_INPUT_READ in this case */ void gtk_handle_audio_input(gpointer data, gint fd _U_, GdkInputCondition condition _U_) { session_t *session = (session_t *) data; switch (session->state) { case STATE_READY: /* we are in command mode */ if (debug > 1) fprintf(stderr, "Warning: Got audio input in ready mode (ALSA?).\n"); /* flush audio input */ read(session->audio_fd_in, session->audio_inbuf, session->fragment_size_in); break; case STATE_DIALING: if (debug > 1) fprintf(stderr, "Warning: Got audio input in dialing mode (ALSA?).\n"); /* flush audio input */ read(session->audio_fd_in, session->audio_inbuf, session->fragment_size_in); break; case STATE_RINGING: if (debug > 1) fprintf(stderr, "Warning: Got audio input in ringing mode (ALSA?).\n"); /* flush audio input */ read(session->audio_fd_in, session->audio_inbuf, session->fragment_size_in); break; case STATE_RINGING_QUIET: if (debug > 1) fprintf(stderr, "Warning: Got audio input in QUIET ringing mode.\n"); /* flush audio input */ read(session->audio_fd_in, session->audio_inbuf, session->fragment_size_in); break; case STATE_CONVERSATION: process_audio_source(session); if (session->samples_out >= session->audio_speed_in) session->samples_out %= session->audio_speed_in; session->no_input++; /* if no more input from isdn came, assume abort and switch back */ if (session->no_input >= 10) { /* XXX: reasonable number? */ if (isdn_blockmode(session->isdn_fd, 0)) fprintf(stderr, "Error: Could not switching off isdn blockmode.\n"); session->no_input = 0; } if (session->aborted) { /* That's it! */ session_deinit_conversation(session, 1); /* 1 == let's hang up (I/O error) */ session_set_state(session, STATE_READY); cid_set_duration(session, NULL); } break; case STATE_SERVICE: if (debug > 1) fprintf(stderr, "Warning: Got audio input in service mode (ALSA?).\n"); /* flush audio input */ read(session->audio_fd_in, session->audio_inbuf, session->fragment_size_in); break; case STATE_PLAYBACK: if (debug > 1) fprintf(stderr, "Warning: Got audio input in playback mode (ALSA?).\n"); /* flush audio input */ read(session->audio_fd_in, session->audio_inbuf, session->fragment_size_in); break; default: fprintf(stderr, "Warning: gtk_handle_audio_input: Unknown session state.\n"); /* flush audio input */ read(session->audio_fd_in, session->audio_inbuf, session->fragment_size_in); } }
/* * callback for gtk on isdn input * * input: data: session (session_t *) * fd: file descriptor where we got the input from * condition: will be GDK_INPUT_READ in this case */ void gtk_handle_isdn_input(gpointer data, gint fd _U_, GdkInputCondition condition _U_) { session_t *session = (session_t *) data; char *temp; switch (session->state) { case STATE_READY: /* we are in command mode */ if (isdn_try_read_line(session)){ /* got new line: something happened */ if (!strncmp(session->isdn_inbuf, "RING/", 5)) { /* -> RINGING state */ session->isdn_inbuf[session->isdn_inbuf_len - 2] = 0; /* caller id update */ session->ring_time = time(NULL); /* save callee's number */ free(session->to); session->to = strdup(&session->isdn_inbuf[5]); cid_add_line(session, CALL_IN, NULL, session->to); if (session_set_state(session, STATE_RINGING)) session_set_state(session, STATE_RINGING_QUIET); } else { /* something else */ if (debug) fprintf(stderr, "Unknown message from ISDN device.\n"); } } break; case STATE_DIALING: if (isdn_try_read_line(session)){ /* a response to our dial request */ if (strstr(session->isdn_inbuf, "BUSY\r\n")) { /* get back to READY */ session_set_state(session, STATE_READY); cid_set_duration(session, _("(BUSY)")); } else if (strstr(session->isdn_inbuf, "VCON\r\n")) { /* let's go! */ session_start_conversation(session); /* including state transition */ } else if (strstr(session->isdn_inbuf, "NO CARRIER\r\n")) { /* timeout? */ session_set_state(session, STATE_READY); cid_set_duration(session, _("(TIMEOUT)")); } else { /* got some other modem answer string while dialing out */ if (debug) fprintf(stderr, "Unknown message from ISDN device.\n"); } } break; case STATE_RINGING: case STATE_RINGING_QUIET: if (isdn_try_read_line(session)){ /* got new line: something happened */ if (strstr(session->isdn_inbuf, "VCON\r\n")) { /* let's go! */ /* will only come in STATE_RINGING */ session_start_conversation(session); /* including state transition */ } else if (strstr(session->isdn_inbuf, "CALLER NUMBER: ")) { /* got Caller ID */ session->isdn_inbuf[session->isdn_inbuf_len - 2] = 0; /* save caller's number */ free(session->from); session->from = strdup(&session->isdn_inbuf[15]); /* complete from field */ cid_set_from(session, session->from); /* execute command if given */ if (session->exec_on_incoming) { temp = strdup(session->exec_on_incoming); substitute(&temp, "%n", session->to); substitute(&temp, "%s", session->from); execute(temp); free(temp); } } else if (strstr(session->isdn_inbuf, "RUNG\r\n")) { /* caller giving up */ session_set_state(session, STATE_READY); cid_set_duration(session, _("(RUNG)")); cid_mark_row(session, session->cid_num - 1, TRUE); } else { /* got some other modem answer string while it rings */ if (debug) fprintf(stderr, "Unknown message from ISDN device.\n"); } } break; case STATE_CONVERSATION: process_isdn_source(session); if (session->samples_in >= ISDN_SPEED) session->samples_in %= ISDN_SPEED; session->no_input = 0; if (session->aborted || session->hangup) { /* That's it! */ if (session->hangup) session_deinit_conversation(session, 0); /* 0 == other side hung up */ else session_deinit_conversation(session, 1); /* 1 == let's hang up (I/O error) */ session_set_state(session, STATE_READY); cid_set_duration(session, NULL); } break; case STATE_SERVICE: if (debug) fprintf(stderr, "Note: Got ISDN input in service mode.\n"); gtk_isdn_input_defer(session); break; case STATE_PLAYBACK: if (debug) fprintf(stderr, "Note: Got ISDN input in playback mode.\n"); gtk_isdn_input_defer(session); break; default: fprintf(stderr, "Warning: gtk_handle_isdn_input: Unknown session state.\n"); gtk_isdn_input_defer(session); } }