 /***********************************************************************
 *
 Sample Code Disclaimer

 Copyright © 2004 PalmSource, Inc. or its subsidiaries.  All
 rights reserved.

 You may incorporate this sample code (the "Code") into your applications
 for Palm OS(R) platform products and may use the Code to develop
 such applications without restriction.  The Code is provided to you on
 an "AS IS" basis and the responsibility for its operation is 100% yours.
 PALMSOURCE, INC. AND ITS SUBSIDIARIES (COLLECTIVELY, "PALM") DISCLAIM
 ALL WARRANTIES, TERMS AND CONDITIONS WITH RESPECT TO THE CODE, EXPRESS,
 IMPLIED, STATUTORY OR OTHERWISE, INCLUDING WARRANTIES, TERMS OR
 CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
 NONINFRINGEMENT AND SATISFACTORY QUALITY.  You are not permitted to
 redistribute the Code on a stand-alone basis and you may only
 redistribute the Code in object code form as incorporated into your
 applications.  TO THE FULL EXTENT ALLOWED BY LAW, PALMSOURCE ALSO EXCLUDES ANY
 LIABILITY, WHETHER BASED IN CONTRACT OR TORT (INCLUDING NEGLIGENCE), FOR
 INCIDENTAL, CONSEQUENTIAL, INDIRECT, SPECIAL OR PUNITIVE DAMAGES OF ANY
 KIND, OR FOR LOSS OF REVENUE OR PROFITS, LOSS OF BUSINESS, LOSS OF
 INFORMATION OR DATA, OR OTHER FINANCIAL LOSS ARISING OUT OF OR IN
 CONNECTION WITH THE USE OR PERFORMANCE OF THE CODE.  The Code is subject
 to Restricted Rights for U.S. government users and export regulations.

 SAMPLE NAME:		SockNotifyTestApp

 FILE:     			SockNotifyTestApp.c

 DESCRIPTION:		Test application for the Socket Notification.
 
 Limitation:		5.2.x and higher ONLY.	

 *
 **********************************************************************/

//
//============================================================================
//
// Registers at a low priority to receive the netTestNotification, opens a
// stream socket on port 9900, primes the socket to send notifications of
// connection requests and data, then waits to receive the notifications.
//
//============================================================================


#include <PalmOS.h>
#include <sys_socket.h>
#include "SockNotifyApp_res.h"

//Application's socket notification constant.
#define netTestNotification	'sknt'

#define EVENTWAITTIME			100
static eventsEnum ApplicationServiceEvent(Boolean noWait);
static MenuBarPtr CurrentMenu;

UInt16 errno;
static Boolean netLibOpened = false;
//static int interface = -1;

#define scrollLines				11
#define scrollHeight			12
#define scrollLeft				0
#define scrollTop				20
#define scrollWidth				160

#define MAXBUFLEN				64
#define AppNetTimeout         20*SysTicksPerSecond()
#define kBufSize 500


#define appFileCreator          'vf1q'    // register your own at http://www.palmos.com/dev/creatorid/
#define appVersionNum           0x01
#define appPrefID               0x00
#define appPrefVersionNum       0x01


static void* str =NULL;
static char* buf1=NULL ;
static UInt16 AppNetRefnum=0;
static NetSocketRef socket=NULL;
typedef struct OurGlobalsType {
	RectangleType	scrollingRectangle;
	UInt16			currentLine;
	Boolean			registered;
	int				fd;
	int				fd1;
	Char			buffer[MAXBUFLEN];
	int				buflen;
} OurGlobalsType;

static OurGlobalsType globals;/*= {
	{scrollLeft, scrollTop, scrollWidth,scrollLines*scrollHeight },
	
	0,
	false,
	0,
	-1,
	"Hello"
	,
	-1
};*/

/***********************************************************************
 *
 *  Internal Structures
 *
 ***********************************************************************/
typedef struct 
{
   NetIPAddr addr;
   UInt16 port;
} HelloNetLibPreferenceType;


/***********************************************************************
 *
 *  Global variables
 *
 ***********************************************************************/
HelloNetLibPreferenceType gPrefs = {};



static Err NotificationCallback(SysNotifyParamType *notifyParamsP);
static void CloseSocket(void);
static Boolean SetValue(UInt16 objID, Int32 value);
static Boolean GetAddr(UInt16 AppNetRefnum, NetIPAddr *addrP, UInt16 *portP);



/***********************************************************************
 *
 * FUNCTION:    GetValue
 *
 * DESCRIPTION: This routine gets the numeric value of the specified
 *              text field.
 *
 * PARAMETERS:  objID  - ID of the field on the main form
 *              valueP - pointer to memory where value is returned
 *
 * RETURNED:    True if successful, false otherwise.
 *
 ***********************************************************************/
static Boolean GetValue(UInt16 objID, Int32 *valueP)
{
   FormType *formPtr;
   UInt16 objIndex;
   FieldType *fieldPtr;
   Char *text;

   formPtr = FrmGetFormPtr(MainForm);
   if (!formPtr) return false;

   objIndex = FrmGetObjectIndex(formPtr, objID);
   fieldPtr = (FieldType*)FrmGetObjectPtr(formPtr, objIndex);
   if (!fieldPtr) return false;

   text = FldGetTextPtr(fieldPtr);
   if (!text) return false;

   *valueP = StrAToI(text);
   return true;
}


/***********************************************************************
 *
 * FUNCTION:    SetValue
 *
 * DESCRIPTION: This routine sets the numeric value of the specified
 *              text field.
 *
 * PARAMETERS:  objID  - ID of the field on the main form
 *              value  - the value to insert
 *
 * RETURNED:    True if successful, false otherwise.
 *
 * NOTES:       Determines the maximum length to use based upon the ID
 *
 ***********************************************************************/
static Boolean SetValue(UInt16 objID, Int32 value)
{
   FormType *formPtr;
   UInt16 objIndex;
   FieldType *fieldPtr;
   MemHandle h, oldHandle;
   Char *text;

   formPtr = FrmGetFormPtr(MainForm);
   if (!formPtr) return false;

   objIndex = FrmGetObjectIndex(formPtr, objID);
   fieldPtr = (FieldType*)FrmGetObjectPtr(formPtr, objIndex);
   if (!fieldPtr) return false;

   if (MainPortField == objID) {
      h = MemHandleNew(6);
   } else {
      h = MemHandleNew(4);
   }
   if (!h) return false;

   text = MemHandleLock(h);
   if (MainPortField == objID) {
      StrPrintF(text, "%u", (UInt16)value);
   } else {
      StrPrintF(text, "%u", (UInt8)value);
   }
   MemHandleUnlock(h);
   oldHandle = FldGetTextHandle(fieldPtr);
   FldSetTextHandle(fieldPtr, h);
   if (oldHandle) MemHandleFree(oldHandle);

   return true;
}


/***********************************************************************
 *
 * FUNCTION:    GetAddr
 *
 * DESCRIPTION: This routine gets the IP address and port that the user
 *              has entered.
 *
 * PARAMETERS:  AppNetRefnum - Reference number of NetLib
 *              addrP        - pointer to memory where address is
 *                             returned
 *              portP        - pointer to memory where port is
 *                             returned
 *
 * RETURNED:    True if the IP address and port are valid, false
 *              otherwise.
 *
 * NOTES:       The only check peformed is to see whether the values
 *              are in the appropriate numeric ranges. This doesn't
 *              check whether the specified host exists or is listening
 *              on the specified port.
 *
 ***********************************************************************/
static Boolean GetAddr(UInt16 AppNetRefnum, NetIPAddr *addrP, UInt16 *portP)
{
   UInt8 i;
   Int32 ip[4];
   Int32 port;
   Char textIP[16];

   // Get the values
   for (i = 0; i < 4; i++) {
      if (!GetValue(MainIP1Field + i, &(ip[i])) ||
          ip[i] > 255 ||
          ip[i] < 0) {
         return false;
      }
   }

   if (!GetValue(MainPortField, &port) ||
       port > 65535 ||
       port < 1) {
      return false;
   }

   StrPrintF(textIP, "%u.%u.%u.%u", (UInt8)ip[0], (UInt8)ip[1], (UInt8)ip[2], (UInt8)ip[3]);
   *addrP = NetLibAddrAToIN(AppNetRefnum, textIP);
   *portP = (UInt16)port;
   return true;
}



/******************************************************************************/

static Char *AddrToAscii(UInt32 addr)
{
	static Char buf[16];

	StrPrintF(buf,"%ld.%ld.%ld.%ld",addr>>24,(addr>>16)&0xFF,(addr>>8)&0xFF,addr&0xFF);
	return(buf);
}

/******************************************************************************/
static void WriteScroll(OurGlobalsType *gP, const Char *textP, UInt16 length)
{
	RectangleType rect;

	if (gP->currentLine < scrollLines) {
		WinDrawChars(textP,length,scrollLeft,scrollTop+scrollHeight*gP->currentLine++);
	} else {
		WinScrollRectangle(&gP->scrollingRectangle,winUp,scrollHeight,&rect);
		WinEraseRectangle(&rect,0);
		WinDrawChars(textP,length,scrollLeft,scrollTop+scrollHeight*(scrollLines-1));
	}
}

/*
Routine to register for notification launch code. 
*/
static void RegisterNotification()
{
	UInt16 cardNo;
    LocalID dbID;

    if (0 != SysCurAppDatabase(&cardNo, &dbID))
      return; // shouldn't ever fail, but just in case.
	
	SysNotifyRegister(cardNo, dbID, netSocketOptSockNotice,NULL, sysNotifyNormalPriority,&globals);
	#if EMULATION_LEVEL == EMULATION_NONE
		ErrNonFatalDisplayIf((err != errNone) && (err != sysNotifyErrDuplicateEntry), "can't register");
#endif
}

/*
Routine to unregister the notification.
*/
static void UnRegisterNotification()
{
	UInt16 cardNo;
    LocalID dbID;

    if (0 != SysCurAppDatabase(&cardNo, &dbID))
      return; // shouldn't ever fail, but just in case.
	
	SysNotifyUnregister(cardNo,dbID,netTestNotification,1);
	
}

/*
Routine to prime the notification so that we can be notified. You have to call this
routine after handling the notification so that you can be notified again!
*/
static Err PrimeSocketNotify(OurGlobalsType *gP)
{
	NetSocketNoticeType notice;
	void *option;
	int fd;

	if (gP->fd1 != -1)
	{
		FrmCustomAlert(helloAlert,"gP->fd1 != -1",NULL,NULL);
		 fd = gP->fd1;
	}
	else if (gP->fd != -1)
	{
		FrmCustomAlert(helloAlert,"gP->fd != -1",NULL,NULL);
	 fd = gP->fd;
	}
	else
	{
		FrmCustomAlert(helloAlert,"return(-1)",NULL,NULL);
		 return(-1);
	}
	notice.condition = 0xFFFFFFFF;	// any event, use more specific conditions if needed.
	
	//This is the only eType which is currently support.
	notice.type = netSocketNoticeNotify;
	notice.notice.notify.notifyType =netSocketOptSockNotice;
	option = &notice;
	
	return(NetLibSocketOptionSet(AppNetRefnum,fd,netSocketOptLevelSocket,
	      netSocketOptSockNotice,&option,sizeof(option),AppNetTimeout,&errno));
	//return(NetLibSocketOptionSet(AppNetRefnum,fd,netSocketOptLevelSocket,
	 //     netSocketOptSockNonBlocking,&option,sizeof(option),AppNetTimeout,&errno));
	      
}

/*
Routine to keep a trace.
*/
static void NotificationCallbackTrace(
	const Char *textP, OurGlobalsType *gP, UInt32 notifyType, SysNotifyNetSocketType *nP)
{
	Char buf[64];
	UInt32 tag[2];

	tag[0] = notifyType;
	tag[1] = 0;
	WriteScroll(gP,buf,
		StrPrintF(buf,"%s: '%s' %x %lx",textP,tag,nP->socketRef,nP->condition));
}


//============================================================================
//
// FUNCTION:		NotificationCallback
//
// DESCRIPTION:	Handler to process the socket notifications. This function can be
//				used as callback or notification handler.
//
// PARAMETERS:		
//
// RETURNED:		
//
//============================================================================

//List of notifications:

/*
#define netSocketNoticeErr					0x00000001
#define netSocketNoticeUDPReceive		0x00000002
#define netSocketNoticeTCPReceive		0x00000004
#define netSocketNoticeTCPTransmit		0x00000008
#define netSocketNoticeTCPRemoteClosed	0x00000010
#define netSocketNoticeTCPClosed			0x00000020
#define netSocketNoticeConnectInbound	0x00000040
#define netSocketNoticeConnectOutbound	0x00000080
*/

static Err NotificationCallback(SysNotifyParamType *notifyParamsP)
{
	SysNotifyNetSocketType *nP = (SysNotifyNetSocketType *)notifyParamsP->notifyDetailsP;
	OurGlobalsType *gP = (OurGlobalsType *)notifyParamsP->userDataP;
	Char buf[MAXBUFLEN];
	int len,option;

	do {
		
		//Check for socket error notification.
		if (nP->condition & netSocketNoticeErr) {
			FrmAlert(helloAlert);
			NotificationCallbackTrace("Error",gP,notifyParamsP->notifyType,nP);
			nP->condition &= ~netSocketNoticeErr;
		//Check for connect notification.
		} else if (nP->condition & netSocketNoticeConnectInbound) {
			FrmAlert(helloAlert);
			NotificationCallbackTrace("Connect",gP,notifyParamsP->notifyType,nP);
			nP->condition &= ~netSocketNoticeConnectInbound;
			if (gP->fd1 != -1) {
				if (gP->buflen) WriteScroll(gP,gP->buffer,gP->buflen);
				close(gP->fd1);
				gP->fd1 = -1;
			}
			gP->fd1 = accept(gP->fd,0,0);
			if (gP->fd1 != -1) {
				FrmAlert(helloAlert);
				gP->buflen = 0;
				option = 1;						//set non-blocking socket option.
				NetLibSocketOptionSet(AppNetRefnum,gP->fd1,netSocketOptLevelSocket,
					netSocketOptSockNonBlocking,&option,sizeof(option),AppNetTimeout,&errno);
				write(gP->fd1,"Hello\15\12",7);
			}
		//Check for data receive notification.
		} else if (nP->condition & netSocketNoticeTCPReceive) {
			FrmAlert(helloAlert);
			NotificationCallbackTrace("Receive",gP,notifyParamsP->notifyType,nP);
			nP->condition &= ~netSocketNoticeTCPReceive;
			if (gP->fd1 != -1) {
				for ( ; ; ) {
					len = read(gP->fd1,buf,sizeof(buf));
					if (len < 0) break;
					buf[len] = 0;
					if(buf[0] == '!')
						CloseSocket();
					WriteScroll(gP,buf,len);
					write(gP->fd1,buf,StrLen(buf));
				}
			}
		//Check for close notification
		} else if (nP->condition & (netSocketNoticeTCPRemoteClosed|netSocketNoticeTCPClosed)) {
			FrmAlert(helloAlert);
			NotificationCallbackTrace("Close",gP,notifyParamsP->notifyType,nP);
			nP->condition &= ~(netSocketNoticeTCPRemoteClosed|netSocketNoticeTCPClosed);
			if (gP->fd1 != -1) {
				if (gP->buflen) WriteScroll(gP,gP->buffer,gP->buflen);
				close(gP->fd1);
				gP->fd1 = -1;
			}
		} else {
			NotificationCallbackTrace("Unknown",gP,notifyParamsP->notifyType,nP);
			nP->condition = 0;
		}
	} while (nP->condition);
	PrimeSocketNotify(gP);					//prime to receive next notification.
	notifyParamsP->handled = true;
	return(0);
}

/******************************************************************************/
/*
Routine to open a listening socket on a given port. 
*/
static void OpenSocket(void)
{
	//struct sockaddr_in address;
		
   UInt16 size=0,bufsize=0;
   Int16 BytesRead=0;
   
	 UInt16 sentBytes=0;
	
	Char buf[64];
	Int16 result;
	const Char *fnameP;
	Err err = 0;
	
	static   NetSocketAddrINType destAddr;
	Err error;
	if (globals.fd != -1) return;
	
	 if (!GetAddr(AppNetRefnum, &gPrefs.addr, &gPrefs.port)) 
   {
      FrmCustomAlert(helloAlert,"INvalid IP",NULL,NULL);
      return ;
   }
	
	 error = SysLibFind("Net.lib", &AppNetRefnum);
   	 
     if (error)
     {     	
     	 return;   
     } 	
	
	socket= NetLibSocketOpen(AppNetRefnum,netSocketAddrINET,netSocketTypeStream,
                             netSocketProtoIPTCP,AppNetTimeout,&error);
    if (error) 
     {
      NetLibClose(AppNetRefnum, false); 
     
      return ;
     }
	globals.fd = socket;
	fnameP = "socket";
	if (globals.fd == -1) goto failed;
	globals.fd1 = -1;

	fnameP = "PrimeSocketNotify";
	err = PrimeSocketNotify(&globals);
	/*if (err) goto failed;
	{   
		FrmCustomAlert(helloAlert,"Gajibaba",NULL,NULL);
		 goto failed;
	}	*/ 
	
	MemSet(&destAddr, sizeof(destAddr), 0);
   destAddr.family = netSocketAddrINET; // This should match the second argument to NetLibSocketOpen
   destAddr.port = gPrefs.port;
   destAddr.addr = gPrefs.addr;
   //error = 0;
	 
	//fnameP = "bind";
	//if (bind(globals.fd,(struct sockaddr *)&address,sizeof(address)) < 0) goto failed;
   result = NetLibSocketConnect(AppNetRefnum,                  // Network library
                                socket,                        // Socket reference
                                (NetSocketAddrType*)&destAddr, // Destination address
                                sizeof(destAddr),              // Length of destAddr
                                -1,                            // Timeout
                                &error                         // Error result
                                );

 if (result == -1)
    { 
      FrmCustomAlert(helloAlert,"Try Little Later",NULL,NULL);
   	  NetLibSocketClose (AppNetRefnum, socket,-1,&error);
    			      //(Network Library,Socket reference,Timeout, Error result) 
     error = NetLibClose(AppNetRefnum, false);
     socket=NULL;
   
     return;
     } 
      	  str = MemPtrNew(kBufSize);
	

    BytesRead = NetLibReceive(AppNetRefnum,socket,str,kBufSize,0,NULL,
    &size,10*SysTicksPerSecond(),&error);

     
 		 if (BytesRead == -1)
			{
			  NetLibSocketClose (AppNetRefnum, socket,-1,&error);     		   
			  error = NetLibClose(AppNetRefnum, false);
			  AppNetRefnum=0;
			  
			  return;
			}
 		if (BytesRead == 0)  
		  {
		   //SysFatalAlert("Socket closed");
		   FrmCustomAlert(helloAlert,"Connection Close by server",NULL,NULL);
   	 	   NetLibSocketClose (AppNetRefnum, socket,-1,&error);
    	   //(Network Library,Socket reference,Timeout, Error result) 
     		error = NetLibClose(AppNetRefnum, false);
     		socket=NULL;
		   
			return ;
			}
else 
	{
	FrmCustomAlert(helloAlert,str,NULL,NULL);	
	}
	bufsize+=StrLen("Login;palm;")+StrLen("durgeshtrivedi@gmail.com")+StrLen("durgesh")+3;
     buf1 = MemPtrNew(bufsize);
	 MemSet(buf1,bufsize,'\0');
    StrPrintF(buf1,"Login;palm;%s;%s;","durgeshtrivedi@gmail.com","durgesh");   
  // Send data
 
   while (sentBytes < bufsize)
    {     
      result = NetLibSend (AppNetRefnum,       // Network library
                           socket,             // Socket reference
                           buf1 + sentBytes,    // Buffer to send
                           bufsize - sentBytes, // Bytes to send from buffer
                           0,                  // Flags
                           NULL,               // Destination address -- does not apply to TCP sockets
                           0,                  // Length of destination address
                           -1,                 // Timeout
                           &error              // Error result
                           );
      if (result == -1)
       {
          break;
         //goto CloseSocket;
        }
      		sentBytes += result;      
   }

		
	   	MemSet(str,StrLen(str),0);
	   	
	   	
	   	
		    BytesRead = NetLibReceive(AppNetRefnum,socket,str,kBufSize,0,NULL,
    &size,10*SysTicksPerSecond(),&error);
	
   		
         if (BytesRead == -1)
           {

			NetLibSocketClose (AppNetRefnum, socket,-1,&error);
     		    //(Network Library,Socket reference,Timeout, Error result) 
     		error = NetLibClose(AppNetRefnum, false);     		
     		if(buf1)MemPtrFree(buf1);
     		return;
		  }
 		if (BytesRead == 0)
			{
				FrmCustomAlert(helloAlert,"Server ShutDown",NULL,NULL);
				if(buf1)MemPtrFree(buf1);
				return ;
			} 
			else 
			  {
			  	//Seperator(&str,recieveBytes,size);
			  	if( StrCompare(str,"Fail") == 0 )
			  	{
			  		 FrmCustomAlert(helloAlert,"Invalid UserName Password",NULL,NULL);
			  		 if(buf1)MemPtrFree(buf1);
			  		 return ;
			  	}				
				else
				{
					FrmCustomAlert(helloAlert,StrIToA(buf,BytesRead),NULL,NULL);
			    	FrmCustomAlert(helloAlert,str,NULL,NULL);								
				}
			  }

	

	//fnameP = "listen";
//	err = listen(globals.fd,1);
	//if (err) goto failed;

	//WriteScroll(&globals,buf,StrPrintF(buf,"%s","Socket Listening..."));

	return;	

failed:
	WriteScroll(&globals,buf,StrPrintF(buf,"%s: %x %x",fnameP,errno,err));
	if (globals.fd != -1) {
NetLibSocketClose(AppNetRefnum, globals.fd,
AppNetTimeout, &errno);
globals.fd = -1;
} 
}

/*
Routine to close the open socket. 
*/
static void CloseSocket(void)
{

	 if (globals.fd1 != -1) {
NetLibSocketClose(AppNetRefnum, globals.fd1,
AppNetTimeout, &errno);
globals.fd1 = -1;
}
if (globals.fd != -1) {
NetLibSocketClose(AppNetRefnum, globals.fd,
AppNetTimeout, &errno);
globals.fd = -1;
} 
}


//============================================================================
//
// FUNCTION:		MainFormHandleEvent
//
// DESCRIPTION:	Handles processing of events for the ̉mainÓ form.
//
// PARAMETERS:		event	- the most recent event.
//
// RETURNED:		True if the event is handled, false otherwise.
//
//============================================================================

static Boolean MainFormHandleEvent(EventPtr eventP)
{
	Boolean handled = false;
	FormType* frm;
	
	if (eventP->eType == menuEvent) {
		switch (eventP->data.menu.itemID) {
			case ActionsOpensocket:
				OpenSocket();
				handled = true;
				break;
			case ActionsClosesocket:
				CloseSocket();
				handled = true;
				break;
		}
	} else if (eventP->eType == frmOpenEvent) {
		   frm = FrmGetActiveForm();
      
      // Load initial values from prefs
      SetValue(MainIP1Field, (gPrefs.addr & 0xFF000000) >> 24);
      SetValue(MainIP2Field, (gPrefs.addr & 0x00FF0000) >> 16);
      SetValue(MainIP3Field, (gPrefs.addr & 0x0000FF00) >> 8);
      SetValue(MainIP4Field, gPrefs.addr & 0x000000FF);
      SetValue(MainPortField, gPrefs.port);
		
		FrmDrawForm(FrmGetActiveForm());
		WriteScroll(&globals,"Ready",5);
		handled = true;
	}

	return(handled);
}


//============================================================================
//
// FUNCTION:    ApplicationHandleEvent
//
// DESCRIPTION: This routine loads form resources and set the event
//              handler for the form loaded.
//
// PARAMETERS:  event  - a pointer to an EventType structure
//
// RETURNED:    true if the event has handle and should not be passed
//              to a higher level handler.
//
//============================================================================

static Boolean ApplicationHandleEvent (EventPtr event)
{
	FormPtr frm;

	if (event->eType == frmLoadEvent) {
		frm = FrmInitForm(event->data.frmLoad.formID);
		FrmSetActiveForm(frm);		
		switch (event->data.frmLoad.formID) {
			case MainForm:
				FrmSetEventHandler(frm,MainFormHandleEvent);
				break;				
		}
		return (true);
	}
	return (false);
}


//============================================================================
//
// FUNCTION:		ApplicationServiceEvent
//
// DESCRIPTION:	Obtains events from the Event
//						Manager and passes them on to various applications and
//						system event handlers before passing them on to
//						FrmHandleEvent for default processing.
//
// PARAMETERS:		None.
//
// RETURNED:		Nothing.
//
//============================================================================

static eventsEnum ApplicationServiceEvent(Boolean noWait)
{
	EventType event;
	UInt16 error;

	// Get the next available event.
	event.eType = nilEvent;
	EvtGetEvent(&event, noWait?0:EVENTWAITTIME);
	if (event.eType != nilEvent) {
		if (!SysHandleEvent(&event))
			if (!MenuHandleEvent(CurrentMenu,&event,&error))
				if (!ApplicationHandleEvent(&event))
					FrmDispatchEvent(&event); 
	}
	return(event.eType);
}


//============================================================================
//
// FUNCTION:		EventLoop
//
// DESCRIPTION:	A simple loop that obtains events from the Event
//						Manager and passes them on to various applications and
//						system event handlers before passing them on to
//						FrmHandleEvent for default processing.
//
// PARAMETERS:		None.
//
// RETURNED:		Nothing.
//
//============================================================================

static void EventLoop(void)
{
	Boolean noWait = false;

	for ( ; ; ) {
		switch (ApplicationServiceEvent(noWait)) {
			case nilEvent:
				noWait = false;
				break;
			case appStopEvent:
				return;
		default:
				break;
		}
	}
}


//============================================================================
//
// FUNCTION:     StartApplication
//
// DESCRIPTION:  This routine sets up the initial state of the application.
//
// PARAMETERS:   None.
//
// RETURNED:     Nothing.
//
//============================================================================

static Err StartApplication(void)
{
	UInt16 netIFErr,openCount;
	Boolean allUp;
	Err err;
	
	UInt16 prefsSize;
   // Read the saved preferences / saved-state information.
  globals.registered = false;
	globals.fd = 0;
	globals.fd1 = -1;
	//globals.buflen=-1;
   prefsSize = sizeof(gPrefs);
   PrefGetAppPreferences(appFileCreator, appPrefID, &gPrefs, &prefsSize, true);
	
	RegisterNotification();
	
	globals.registered = true;
	globals.fd = -1;
	
	//find the netlib reference.
	err = SysLibFind("Net.lib", &AppNetRefnum);
	if(err)
		return err;
	
	//check if it is already open.
	NetLibOpenCount(AppNetRefnum,&openCount);
	if (openCount > 0) {
		err = NetLibConnectionRefresh(AppNetRefnum,false,&allUp,&netIFErr);
		if (err || netIFErr || !allUp) return(-1);
	} else {
		// Open the NetLib in the current config
		err = NetLibOpen(AppNetRefnum,&netIFErr);
		if (err && (err != netErrAlreadyOpen)) return(err);
		netLibOpened = true;
	}

	//Two ways to register for socket notices:
	
	//(1)
	
	// Register to receive the netTestNotification notification callback.
	//SysNotifyRegister(0,sysNotifyNoDatabaseID,netTestNotification,NotificationCallback,1,&globals);
	
	//(2)
	
	//Register to receive the netTestNotification notification launch code.
	

	return(0);
}


//============================================================================
//
// FUNCTION:     StopApplication
//
// DESCRIPTION:  This routine shuts down the application.
//
// PARAMETERS:   None.
//
// RETURNED:     Nothing.
//
//============================================================================

static void StopApplication(void)
{

	CloseSocket();
	if (globals.registered) {
		
		//Depending on which way you registered, you need to unregistere.
		
		//(1)
		//Unregister to receive netTestNotification notification callback.
		//SysNotifyUnregister(0,sysNotifyNoDatabaseID,netTestNotification,1);
		
		//(2)
		// Unregister to receive the netTestNotification notification launch code.
		UnRegisterNotification();
		
		globals.registered = false;
	}
	if (netLibOpened) {
		NetLibClose(AppNetRefnum,false);
		netLibOpened = false;
	}
	FrmCloseAllForms();
}

//============================================================================
//
// FUNCTION:		PilotMain
//
// DESCRIPTION:	This function is the equivalent of a main() function
//						in standard ̉CÓ.  It is called by the Emulator to begin
//						execution of this application.
//
// PARAMETERS:		cmd - command specifying how to launch the application.
//						cmdPBP - parameter block for the command.
//						launchFlags - flags used to configure the launch.			
//
// RETURNED:		Any applicable error code.
//
//============================================================================

UInt32 PilotMain(UInt16 cmd, MemPtr cmdPBP, UInt16 launchFlags)
{

	switch (cmd) {
		case	sysAppLaunchCmdNormalLaunch:
			if (StartApplication()) break;
			FrmGotoForm(MainForm);
			EventLoop();
			StopApplication();
			break;
			
		case sysAppLaunchCmdNotify:
		{
			SysNotifyParamType *notifyP = (SysNotifyParamType *)cmdPBP;			
			NotificationCallback(notifyP);
		}
			break;

		default:
			break;
	}
	return(0);
}

