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
[email protected]
https://maemo.org/mailman/listinfo/maemo-developers