On Tue, 2006-14-03 at 09:04 +0200, Kalle Valo wrote: > "Steven Hill" <[EMAIL PROTECTED]> writes: > > >> Good. But actually disabling the idle timer is just a workaround. It > >> seems that the real problem is the application crashing whenever a > >> disconnect from a network happens. > > > > I agree, but it is not clear what is happening. The messages I am seeing > > from my application are: > > > > Received status_changed to DISCONNECTING notification for IAP shss > > Received status_changed to IDLE for IAP shss > > Segmentation fault > > > > The OSSO_IAP_DISCONNECTED event in the iap_callback function does not > > appear to be reached, because it should print a brief message on entry. > > Ok, so this points to a bug in libosso-ic.so (the library providing > the IC API) and I'll have to investigate this more. Can you give any > instructions how to reproduce it? I haven't seen this before so I > suspect there's something special needed for triggering this bug. What > 770 software version are you using? > > > Do you know where the status_changed messages are being generated? > > It's printed from libosso-ic.so. To be precise from src/ic-api.c line 104 > which is in debian source package osso-ic-oss. > I am running this app on (I believe) the most recent production version of the 770 (downloaded and installed using the Windows flasher - according to the Device information it is 3.2005.51-13. I have attached my network.c file and two header files. The connection code is based on the osso-ic example with a few changes and additions. Network connection is made with a call to get_connected. Let me know if this helps...
Steve Hill
/* * This file is part of DayCareLogin * * Copyright (C) 2006 SH Scientific Systems * * This software is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef LOGINAPP_APPDATA_H #define LOGINAPP_APPDATA_H #include <libosso.h> #include <network.h> #include <hildon-widgets/gtk-infoprint.h> #include <hildon-widgets/hildon-app.h> #include <sqlite.h> #include <gtk/gtk.h> #include <libgnomevfs/gnome-vfs.h> #include <libgnomevfs/gnome-vfs-utils.h> #define dbaseFileName "~/securetrak_data.db" #define IPaddrFileName "~/defaultIP.txt" #define XMLFileName "~/temp.xml" #define OutXMLFileName "~/out.xml" #define PINGTIME 30000 /* Time in milliseconds between pings */ typedef struct _AppData AppData; typedef struct _PwdData PwdData; /*typedef struct _OutBufData OutBufData;*/ typedef struct _AppContext AppContext; typedef struct _ChildChkWindow ChildChkWindow; typedef struct _AttendCheck AttendCheck; typedef struct _ThanksWindow ThanksWindow; typedef struct _StaffWindow StaffWindow; struct _StaffWindow { HildonAppView *staff_view; GtkWidget *Name_label; GtkWidget *Time_label; gchar *name; gchar *ID; gchar *In; }; struct _ThanksWindow { HildonAppView *thankyou_view; GtkWidget *Comment_label; GtkWidget *Time_label; }; struct _AttendCheck { gboolean in; /* if TRUE, checkin in status */ GnomeVFSHandle *xmlOut; /* Pointer to handle of file holding XML login/out info */ gchar *gid; /* The guardian ID as a string */ }; struct _AppContext { const char *host, *port; char iap_name[IAP_LENGTH]; APPState appstate; READState readstate; GIOChannel *channel; guint read_watch, write_watch; gboolean server_connected; gboolean recent_io; }; struct _PwdData { guint8 pwd_digits; /*Number of digits entered in password */ gchar pwd[4]; /*The password string*/ }; struct _ChildChkWindow { HildonAppView *child_checkin_view; GtkWidget *Guardian_name; GtkWidget *Date_label; GtkWidget *Time_label; GtkTreeView *Checked_in_view; GtkTreeView *Checked_out_view; gchar *Guardian_id; }; struct _AppData { HildonApp *app; /*handle to application */ AppContext *connection; /* handle to the network connection context */ HildonAppView *login_view; /*handle to the login view */ ChildChkWindow *child_checkin; ThanksWindow *thanks; StaffWindow *staff; gint Timeout_tag; /*pointer to allow destruction of timeout callback */ osso_context_t *osso; /*handle to osso */ PwdData* pwdPtr; /*pointer to password information */ GnomeVFSHandle *xmlOut; /* Pointer to handle of file holding XML login/out info */ }; #endif
#include <appdata.h> #include <osso-ic.h> #include <libgnomevfs/gnome-vfs.h> #include <libgnomevfs/gnome-vfs-utils.h> extern GnomeVFSHandle *xml_h; extern guint16 xml_crc; extern gboolean new_xml_file; extern sqlite *dbPtr; /* Prototypes */ void iap_callback(struct iap_event_t *event, void *arg); void connect_server(AppData *adPtr); gboolean read_handler(GIOChannel *source, GIOCondition condition, gpointer data); gboolean write_handler(GIOChannel *source, GIOCondition condition, gpointer data); gboolean get_connected(AppData* adPtr); void calc_crc(gchar c, guint16 *crc); /* This is the table used to calculate the CRC value for data packets in and out. It is based on nibble by nibble processing using the reflected algorithm. */ guint crc_tbl1[] = { 0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401, 0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400, }; gboolean read_handler(GIOChannel *source, GIOCondition condition, gpointer data) { gsize bytes; gchar buffer[BUFFER_SIZE]; GIOStatus status; gint n, m; GnomeVFSResult fr; AppContext *ctxt; static gint nbuf, nwrite; static gchar bsave[3]; static gint8 bcount; /* static guint16 crcval;*/ static gint num_to_read, num_read; ctxt = ((AppData *)data)->connection; g_assert(data != NULL); if (condition & G_IO_IN) { status = g_io_channel_read_chars(source, buffer, BUFFER_SIZE, &bytes, NULL); if ((status == G_IO_STATUS_NORMAL) && (bytes > 0)) { ctxt->recent_io = TRUE; nbuf++; for(n=0; n<bytes; n++) { switch(ctxt->readstate) { case READ_NOTHING: if(buffer[n] == 0xff) { ctxt->readstate = READ_NUM; bcount = 0; nbuf = 0; /*crcval = 0xFFFF; calc_crc(0xff, &crcval);*/ /* Open a temporary XML file */ fr = gnome_vfs_create(&xml_h, gnome_vfs_expand_initial_tilde (XMLFileName), GNOME_VFS_OPEN_WRITE, FALSE, 0777); } break; case READ_NUM: bsave[bcount++] = buffer[n]; /*calc_crc(buffer[n], &crcval);*/ if(bcount == 3) { num_to_read = (bsave[0] & 0x7f) * 16384; num_to_read += (bsave[1] & 0x7f) * 128 ; num_to_read += (bsave[2] & 0x7f); num_read = 4; ctxt->readstate = READ_XML; printf("Have the number... %d\n", num_to_read); nbuf = 0; nwrite = 0; bcount = 0; } break; case READ_XML: m = bytes - n; num_read += m; if(num_read >= num_to_read) { num_read -= m; m = num_to_read - num_read; num_read += m; if(m==0) { ctxt->readstate = READ_NOTHING; new_xml_file = TRUE; bcount = 0; gnome_vfs_close(xml_h); } gtk_infoprintf(NULL, "Have the file... %d", num_read); } if(m>0) { /*for(i=0; i<m; i++) calc_crc(buffer[n+i], &crcval);*/ GnomeVFSResult fr; GnomeVFSFileSize bytes_written; fr = gnome_vfs_write(xml_h,buffer+n, (GnomeVFSFileSize)m, &bytes_written); if(fr != GNOME_VFS_OK) { gtk_infoprintf(NULL,"XML Prob: writ = %d n = %d bytes = %d m = %d nbuf = %d ret = %d",num_read, n, bytes,m, nbuf, (int)fr); printf("Problem writing XML file! Return = %d\n", (int)fr); } else nwrite++; if(num_read == num_to_read) { gnome_vfs_close(xml_h); printf("File written. %d writes\n",nwrite); new_xml_file = TRUE; bcount = 0; ctxt->readstate = READ_NOTHING; /* emit a signal */ } n+=(m-1); } break; /* case READ_CRC: printf("n %d byte %0x\n", n, buffer[n]); bsave[bcount++] = buffer[n]; if(bcount == 3) { xml_crc = (bsave[0] & 0x3) * 16384; xml_crc += ((bsave[1] & 0x7f) * 128); xml_crc += (bsave[2] & 0x7f); bcount = 0; ctxt->readstate = READ_NOTHING; printf("CRC = %d\n", xml_crc); calc_crc((xml_crc & 0xff), &crcval); calc_crc((xml_crc >> 8), &crcval); printf("Final crc = %d\n", crcval); /* Emit a signal? } break;*/ default: /* gtk_infoprint(NULL, "In default");*/ break; } } } else { printf("Couldn't read from the channel.\n"); ctxt->server_connected = FALSE; return FALSE; } } if (condition & G_IO_ERR) { printf("G_IO_ERR from channel.\n"); ctxt->server_connected = FALSE; return FALSE; } if (condition & G_IO_HUP) { printf("G_IO_HUP from channel.\n"); ctxt->server_connected = FALSE; return FALSE; } return TRUE; } void calc_crc(gchar c, guint16 *crc) { *crc = crc_tbl1[(c ^ *crc) & 15] ^ (*crc >> 4); *crc = crc_tbl1[((c >> 4) ^ *crc) & 15] ^ (*crc >> 4); } /*gboolean write_handler(GIOChannel *source, GIOCondition condition, gpointer data) { gsize bytes; gchar buf[256]; guint8 n = 0; AppContext *ctxt = ((AppData*)data)->connection; OutBufData* obPtr = ((AppData*)data)->outbufPtr; if (condition & G_IO_OUT && ctxt->appstate == APPSTATE_CONNECTED) { if(obPtr->inPtr != obPtr->outPtr) { while(obPtr->outPtr != obPtr->inPtr){ buf[n++]=obPtr->buf[obPtr->outPtr++]; } g_io_channel_write_chars(source, buf, (gssize)n, &bytes, NULL); /* Should do something here to deal with the case where the entire buffer is not written g_io_channel_flush(source, NULL); ctxt->appstate = APPSTATE_REQUEST_SENT; return FALSE; } } return TRUE; }*/ void iap_callback(struct iap_event_t *event, void *arg) { AppContext* ctxt = ((AppData*)arg)->connection; g_assert(ctxt != NULL); switch (event->type) { case OSSO_IAP_CONNECTED: printf("OSSO_IAP_CONNECTED\n"); if (ctxt->appstate == APPSTATE_CONNECTING) { ctxt->appstate = APPSTATE_CONNECTED; strncpy(ctxt->iap_name, event->iap_name, IAP_LENGTH); connect_server(arg); } break; case OSSO_IAP_DISCONNECTED: printf("OSSO_IAP_DISCONNECTED\n"); if (ctxt->appstate == APPSTATE_CONNECTED) { if (strncmp(event->iap_name, ctxt->iap_name, IAP_LENGTH) == 0) { ctxt->appstate = APPSTATE_DISCONNECTED; printf( "IAP disconnected.\n"); if(ctxt->server_connected) { g_io_channel_shutdown(ctxt->channel, FALSE, NULL); g_io_channel_unref(ctxt->channel); ctxt->server_connected = FALSE; } } } break; case OSSO_IAP_ERROR: printf("OSSO_IAP_ERROR error_code=0x%x\n", -event->u.error_code); printf("There was an IAP error.\n"); ctxt->appstate = APPSTATE_DISCONNECTED; if(ctxt->server_connected) { g_io_channel_shutdown(ctxt->channel, FALSE, NULL); g_io_channel_unref(ctxt->channel); ctxt->server_connected = FALSE; } break; } } void connect_server(AppData *adPtr) { int fd; struct addrinfo hints, *addrinfo; gchar *strdata, fbuf[1024]; GnomeVFSResult fr; GnomeVFSFileSize bytes_read, bytes_written, bytes_to_write; gssize bytes; AppContext* ctxt = adPtr->connection; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; ctxt->server_connected = FALSE; if (getaddrinfo(ctxt->host, ctxt->port, &hints, &addrinfo) != 0) { printf("getaddrinfo() failed.\n"); } else { if ((fd = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol)) == -1) { printf("socket create error\n"); } else { if (connect(fd, addrinfo->ai_addr, addrinfo->ai_addrlen) == -1) { switch (errno) { case EINPROGRESS: printf("connection in progress\n"); break; default: close(fd); printf("Could not connect!\n"); } if(dbPtr == NULL) { printf("No database available - quitting!\n"); gtk_main_quit(); } } else { ctxt->channel = g_io_channel_unix_new(fd); g_io_channel_set_encoding(ctxt->channel, NULL, NULL); /* For binary data */ /* g_io_channel_seek_position(ctxt->channel, 0, G_SEEK_END, NULL);*/ g_io_channel_set_flags(ctxt->channel, g_io_channel_get_flags(ctxt->channel) | G_IO_FLAG_NONBLOCK, NULL); ctxt->read_watch = g_io_add_watch(ctxt->channel, G_IO_IN | G_IO_ERR | G_IO_HUP, read_handler, adPtr); /* ctxt->write_watch = g_io_add_watch(ctxt->channel,G_IO_OUT, write_handler, adPtr);*/ ctxt->server_connected = TRUE; printf("Connected, sending first xml data...\n"); if(adPtr->xmlOut != NULL) { strdata = g_strdup_printf("</loginfo>"); bytes_to_write=strlen(strdata); fr = gnome_vfs_seek(adPtr->xmlOut, GNOME_VFS_SEEK_END, 0); if(fr != GNOME_VFS_OK) printf("Problems with seek end of XML file. Return = %d\n", fr); else { fr = gnome_vfs_write(adPtr->xmlOut,strdata, bytes_to_write, &bytes_written); if(fr != GNOME_VFS_OK) printf("Can't write final XML output to file! Return = %d\n", fr); else { /* now re-read the file and transmit it */ fr = gnome_vfs_seek(adPtr->xmlOut, GNOME_VFS_SEEK_START, 0); if(fr != GNOME_VFS_OK) printf("Problems with seek start of XML file. Return = %d\n", fr); else { do { fr = gnome_vfs_read(adPtr->xmlOut, fbuf, 1024, &bytes_read); if(fr != GNOME_VFS_OK) printf("Can't read XML output from file! Return = %d\n", fr); else { g_io_channel_write_chars(ctxt->channel, fbuf, (gssize)bytes_read, &bytes, NULL); g_io_channel_flush(ctxt->channel, NULL); ctxt->recent_io = TRUE; } }while(bytes == 1024); } } } g_free(strdata); gnome_vfs_close(adPtr->xmlOut); strdata = gnome_vfs_expand_initial_tilde (OutXMLFileName); remove(strdata); } else { strdata = g_strdup_printf("<loginfo></loginfo>"); bytes_to_write=strlen(strdata); g_io_channel_write_chars(ctxt->channel, strdata, (gssize)bytes_to_write, &bytes, NULL); g_io_channel_flush(ctxt->channel, NULL); ctxt->recent_io = TRUE; } g_free(strdata); adPtr->xmlOut = NULL; } } freeaddrinfo(addrinfo); } } gboolean get_connected(AppData *adPtr) { if (osso_iap_cb(iap_callback) != OSSO_OK) { printf("osso_iap_cb failed\n"); return FALSE; } adPtr->connection->appstate = APPSTATE_CONNECTING; if (osso_iap_connect(OSSO_IAP_ANY, OSSO_IAP_REQUESTED_CONNECT, adPtr) != OSSO_OK) { printf("osso_iap_connect failed\n"); adPtr->connection->appstate = APPSTATE_DISCONNECTED; return FALSE; } return TRUE; }
#include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #include <sys/types.h> #include <string.h> #include <netdb.h> #include <glib.h> #define DBUS_API_SUBJECT_TO_CHANGE /*#include <appdata.h>*/ #include <osso-ic.h> #define BUFFER_SIZE 1024 #define IAP_LENGTH 21 #ifndef LOGINAPP_NETWORK_H #define LOGINAPP_NETWORK_H typedef enum { APPSTATE_DISCONNECTED=1, APPSTATE_CONNECTING, APPSTATE_CONNECTED } APPState; typedef enum { READ_NOTHING=1, READ_NUM, READ_XML/*, READ_CRC*/ } READState; /*typedef struct _AppContext AppContext; struct _AppContext { const char *host, *port; char iap_name[IAP_LENGTH]; APPState appstate; GIOChannel *channel; guint read_watch, write_watch; gboolean server_connected; };*/ #endif
_______________________________________________ maemo-developers mailing list maemo-developers@maemo.org https://maemo.org/mailman/listinfo/maemo-developers