From: Paul Fertser Date: Tue, 20 Jan 2009 22:44:39 +0000 (+0300) Subject: Implement proper channel allocation and dealloction X-Git-Tag: 0.9.3~4 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=b8949ff6ef8f7c5d2e37170e4005d2dd968d2b77;p=gsm0710muxd.git Implement proper channel allocation and dealloction With this patch the muxer will allocate channels in a clean way, it will not return a pts until the modem is really ready to operate on this channel. It will also retry the command several times until the channel is allocated. Channel deallocation is also greatly improved, now we send a correct code to close a channel and will repeat several times if the packet somehow (e.g. modem was in power-saving state) lost. --- diff --git a/src/gsm0710muxd.c b/src/gsm0710muxd.c index cb8df03..ecbf608 100644 --- a/src/gsm0710muxd.c +++ b/src/gsm0710muxd.c @@ -148,6 +148,7 @@ typedef struct Channel char* devicename; int fd; int opened; + int frames_allowed; unsigned char v24_signals; char* ptsname; char* origin; @@ -291,6 +292,12 @@ static int baud_rate_index( return -1; } +gboolean glib_returnfalse( + gpointer data) +{ + return FALSE; +} + /** * Calculates frame check sequence from given characters. * @@ -525,6 +532,36 @@ static int handle_channel_data( static int logical_channel_close(Channel* channel) { + guint timeout_id; + GSource *timeout_source; + int write_retries; + + LOG(LOG_DEBUG, "Enter"); + if (channel->opened) + { + LOG(LOG_INFO, "Logical channel %d for %s closing", channel->id, channel->origin); + for (write_retries=0; write_retriesid, NULL, 0, GSM0710_TYPE_DISC | GSM0710_PF); + else + write_frame(channel->id, close_channel_cmd, 2, GSM0710_TYPE_UIH); + timeout_id = g_timeout_add_seconds(3, glib_returnfalse, NULL); + timeout_source = g_main_context_find_source_by_id(NULL, timeout_id); + do + { + LOG(LOG_DEBUG, "g_main_context_iteration"); + g_main_context_iteration(NULL, TRUE); + } + while (channel->opened && !g_source_is_destroyed(timeout_source)); + if (!channel->opened) + break; + } + /* No need to explicitly destroy this source */ + if (channel->opened) + LOG(LOG_WARNING, "Unable to properly close a channel"); + } + if (channel->g_source >= 0) g_source_remove(channel->g_source); channel->g_source = -1; @@ -541,6 +578,7 @@ static int logical_channel_close(Channel* channel) free(channel->origin); channel->origin = NULL; channel->opened = 0; + channel->frames_allowed = 0; channel->v24_signals = 0; channel->remaining = 0; return 0; @@ -555,6 +593,7 @@ static int logical_channel_init(Channel* channel, int id) channel->ptsname = NULL; channel->tmp = NULL; channel->origin = NULL; + channel->opened = 0; return logical_channel_close(channel); } @@ -595,21 +634,11 @@ gboolean pseudo_device_read(GIOChannel *source, GIOCondition condition, gpointer return TRUE; } // dropped connection - if (cmux_mode) - write_frame(channel->id, NULL, 0, GSM0710_CONTROL_CLD | GSM0710_CR); - else - write_frame(channel->id, close_channel_cmd, 2, GSM0710_TYPE_UIH); logical_channel_close(channel); - LOG(LOG_INFO, "Logical channel %d for %s closed", channel->id, channel->origin); } else if (condition == G_IO_HUP) { - if (cmux_mode) - write_frame(channel->id, NULL, 0, GSM0710_CONTROL_CLD | GSM0710_CR); - else - write_frame(channel->id, close_channel_cmd, 2, GSM0710_TYPE_UIH); logical_channel_close(channel); - LOG(LOG_INFO, "Logical channel %d for %s closed", channel->id, channel->origin); } LOG(LOG_DEBUG, "Leave"); return FALSE; @@ -666,6 +695,9 @@ static gboolean c_alloc_channel(const char* origin, const char** name) { LOG(LOG_DEBUG, "Enter"); int i; + guint timeout_id; + GSource *timeout_source; + int write_retries; if (serial.state == MUX_STATE_MUXING) for (i=1;ichannel].opened) { - SYSCHECK(logical_channel_close(channellist+frame->channel)); LOG(LOG_INFO, "Logical channel %d for %s closed", frame->channel, channellist[frame->channel].origin); + channellist[frame->channel].opened = 0; } else { @@ -1721,11 +1774,6 @@ static int close_devices() if (channellist[i].opened) { LOG(LOG_INFO, "Closing down the logical channel %d", i); - if (cmux_mode) - write_frame(i, NULL, 0, GSM0710_CONTROL_CLD | GSM0710_CR); -//multiplexer close down command doesn't work with benqM22a module, use: write_frame(0, NULL, 0, GSM0710_TYPE_DISC | GSM0710_PF); - else - write_frame(i, close_channel_cmd, 2, GSM0710_TYPE_UIH); SYSCHECK(logical_channel_close(channellist+i)); } LOG(LOG_INFO, "Logical channel %d closed", channellist[i].id); @@ -1972,7 +2020,8 @@ int main( g_main_loop_run(main_loop); // will/may be terminated in signal_treatment g_main_loop_unref(main_loop); //finalize everything - SYSCHECK(close_devices()); +// Don't bother with closing devices, mainloop is not running anymore +// SYSCHECK(close_devices()); free(serial.adv_frame_buf); gsm0710_buffer_destroy(serial.in_buf); LOG(LOG_INFO, "Received %ld frames and dropped %ld received frames during the mux-mode",