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

Reply via email to