📄 pushregistry.c
字号:
/* * @(#)pushregistry.c 1.42 02/10/22 @(#) * * Copyright (c) 1999-2002 Sun Microsystems, Inc. All rights reserved. * PROPRIETARY/CONFIDENTIAL * Use is subject to license terms. *//*========================================================================= * Virtual Machine *========================================================================= * SYSTEM: MIDP native * SUBSYSTEM: Push Registry Persistent File Management * FILE: pushregistry.c * OVERVIEW: Opens the push registry file and caches the contents in * memory at startup. Subsequent additions and deletions * update the cache and rewrite the persistent data file. *=======================================================================*//*========================================================================= * Include files *=======================================================================*/#include "kni.h"#include <stdio.h>#include "midpMalloc.h"#include "storage.h"#ifdef UNIX#include <poll.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#else#include <windows.h>#ifndef atoll#define atoll(x) _atoi64(x)#endif /* atoll */#ifdef GCC#include <winsock.h>#else#ifndef _WINSOCKAPI_#include <winsock2.h>#endif /* _WINSOCKAPI_ */#endif /* GCC */#endif /* UNIX */#include <errno.h>static char *appdir = NULL;static char *pushpathname = NULL;static char *alarmpathname = NULL;static int pushfd; static char *errStr = NULL;/* buffer size for line parsing */#define MAX_LINE 512#ifndef MAX_HOST_LENGTH#define MAX_HOST_LENGTH 256#endif /* MAX_HOST_LENGTH */#ifndef MAX_DATAGRAM_LENGTH#define MAX_DATAGRAM_LENGTH 1500#endif /* MAX_DATAGRAM_LENGTH */typedef struct _datagramentry { int ipAddress; int port; int length; char buffer[MAX_DATAGRAM_LENGTH];} DatagramEntry;typedef struct _pushentry { struct _pushentry *next; char *value; char *storagename; char *filter; int fd; int fdsock; int port; int state; DatagramEntry *dg; } PushEntry;typedef struct _alarmentry { struct _alarmentry *next; char *midlet; char *storagename; jlong wakeup;} AlarmEntry;#define LAUNCH_PENDING (-4)#define CHECKED_IN (-3)#define CHECKED_OUT (-2)#define AVAILABLE (-1)static PushEntry *pushlist = NULL;static AlarmEntry *alarmlist = NULL;static int pushlength = 0;static void pushProcessPort(char *buffer, int *fd, int *port);static void alarmopen();static void alarmsave();static int alarmadd(char *str, jlong alarm, jlong *lastalarm);static jlong alarmcheck(jlong time);static void pushListFree();static void alarmListFree();static char *pushfindfd(jlong fd);static int parsePushList ();static int checkfilter(char *filter, char *ip);static void pushcheckinentry(PushEntry *p);static void pushcleanupentry(PushEntry *p);/* * Extract the storage name from the connection value string */static char *pushstorage(char *value, int field) { char *storagefield; char *storagename= NULL; int comma = 0 ; for (storagefield = value; *storagefield; storagefield++) { if (*storagefield == ',') comma ++; /* Push entry contains "connection, midletname, filter, storage" */ /* Alarm entry contains "midletname, alarm, storage" */ if (comma == field) { storagename = storagefield + 1; break; } } return storagename;}/* * Extract the filter from the connection value string */static char *pushfilter(char *value) { char *filterfield = NULL; char filter[MAX_HOST_LENGTH]; int i = 0 ; /* Push entry contains "connection, midletname, filter, storage" */ for (filterfield = pushstorage(value, 2); *filterfield; filterfield++) { if (*filterfield == ',') break; filter[i++] = *filterfield; } filter[i] = '\0'; return midpStrdup(filter);}/* * Open the Push Registry file, if it exists and populate * an in memory cache of the file contents. */void pushopen() { /* Make sure the network is properly in itialized. */ networkInit(); /* Get the storage directory. */ if (appdir == NULL) { /* * On first use initialize the fully qualified pathnames * of the push and alarm persistent files. */ if ((appdir = getStorageRoot()) != NULL) { if (pushpathname = (char*) midpMalloc(strlen(appdir) + 13)) { strcpy(pushpathname, appdir); strcat(pushpathname, "pushlist.txt"); } if (alarmpathname = (char*) midpMalloc(strlen(appdir) + 14)) { strcpy(alarmpathname, appdir); strcat(alarmpathname, "alarmlist.txt"); } } else { /* NYI - no storage directory found. */ } /* * If no memory can be allocated, exit. */ if (appdir == NULL || pushpathname == NULL || alarmpathname == NULL) { fprintf(stderr, "Error: pushopen out of memory.\n"); exit(-1); } } /* Now read the registered connections.*/ if ((pushfd = storageOpen(&errStr, pushpathname, OPEN_READ)) != -1){ /* Read through the file one line at a time */ if (parsePushList() == -2) { fprintf(stderr, "Error: pushopen out of memory " "when parsing push list.\n"); exit(-1); } /* Close the storage handle */ storageClose (&errStr, pushfd); } else { if (errStr != NULL) { /* fprintf (stderr, "Warning: could not open push registration file(%s): %s\n", pushpathname, errStr); */ storageFreeError(errStr); } } alarmopen();}/* * Destroy the push and alarm memory resources. Maintain the push * registrations in the push registry file. */void pushclose() { pushListFree(); alarmListFree(); midpFree(pushpathname); midpFree(alarmpathname);}/* * Save the in memory cache of push registrations to a persistent * file for use in subsequent runs. */static void pushsave() { PushEntry *p; if ((pushfd = storageOpen(&errStr, pushpathname, OPEN_READ_WRITE_TRUNCATE)) != -1){ /* Write a new list of push registrations to the persistent file */ for (p = pushlist; p != NULL ; p = p->next) { storageWrite(&errStr, pushfd, p->value, strlen(p->value)); storageWrite(&errStr, pushfd, "\n", 1); } /* Close the storage handle */ storageClose (&errStr, pushfd); } else { if (errStr != NULL) { fprintf (stderr, "Warning: could not write push registration file(%s): %s\n", pushpathname, errStr); storageFreeError(errStr); return; } }}/* * Add one entry to the push registry. * If the entry already exists return an error. * On succesful registration, write a new copy of the file to disk. * Return -2 if out of memory */static int pushadd(char *str){ PushEntry *p; PushEntry *pe; int comma; char *cp; /* Count the characters up to the first comma. */ for (comma = 0, cp = str; *cp; comma++, cp++) { if (*cp == ',') { break; } } /* Check if the entry already exists? */ for (p = pushlist; p != NULL ; p = p->next) { if (strncmp (str, p->value, comma) == 0) { return -1 ; } } /* Add the new entry. */ if (pe = (PushEntry *) midpMalloc (sizeof(PushEntry))){ pe->next = pushlist ; pe->value = midpStrdup(str); pe->storagename = midpStrdup(pushstorage(pe->value, 3)); if ((pe->value == NULL) || (pe->storagename == NULL)) { midpFree(pe->value); midpFree(pe->storagename); midpFree(pe); return -2; } else { pe->filter = pushfilter(pe->value); pushProcessPort(str, &(pe->fd), &(pe->port)); pe->state = AVAILABLE ; pe->fdsock = -1; pe->dg = NULL; pushlist = pe ; pushlength++; } } if (pe != NULL) { pushsave(); return 0; } return -2;}/* * Remove one entry from the push registry. * If the entry is not registered return an error. * On successful deletion, write a new copy of the file to disk. */static int pushdel(char *str, char *store) { PushEntry *p; PushEntry *lastp = pushlist; PushEntry *tmp; /* Find the entry to remove */ for (p = pushlist; p != NULL ; p = tmp) { tmp = p->next; if (strncmp (str, p->value, strlen(str)) == 0) { /* Check if the connection belongs to another suite. */ if (strcmp(store, p->storagename) != 0) { return -2 ; } /* * Close the socket connection if the entry is being removed. * Only close the connection, if it is not already opened * by the application or in the middle of fielding a * connection notification. */ if (p->fd != -1 && p->state != LAUNCH_PENDING && p->state != CHECKED_OUT) { prim_com_sun_midp_io_j2me_serversocket_Protocol_close(p->fd); p->fd = -1; } /* Clear the pending notification flag. */ if (p->state != LAUNCH_PENDING) { p->state = AVAILABLE; } pushcleanupentry(p); /* Remove the registration entry. */ if (p == pushlist){ /* Replace the top of the list. */ pushlist = p->next; } else { lastp->next = p->next; } pushlength-- ; midpFree(p->value); p->value = NULL; midpFree(p->filter); p->filter = NULL; midpFree(p->storagename); p->storagename = NULL; midpFree(p); pushsave(); return 0; } lastp = p ; } return -1; }/* * Fetch a buffer datagram */int pusheddatagram (int fd, int *ip, int *port, char *buf, int len) { PushEntry *p; PushEntry *tmp; int length = -1; /* Find the entry to pass off the open file descriptor. */ for (p = pushlist; p != NULL ; p = tmp) { tmp = p->next; if (p->fd == fd) { /* Return the cached data. */ if (p->dg == NULL) { return -1; } *ip = p->dg->ipAddress; *port = p->dg->port; length = p->dg->length; if (length > 0) { memcpy(buf, p->dg->buffer, (len < length? len : length)); } /* Destroy the cached entry after it has been read. */ midpFree(p->dg); p->dg = NULL; return length; } } return -1; }/* * Check out the file descriptor for the requested server socket. */int pushcheckoutaccept(int fd) { PushEntry *p; PushEntry *tmp; int temp; /* Find the entry to pass off the open file descriptor. */ for (p = pushlist; p != NULL ; p = tmp) { tmp = p->next; if (p->fd == fd) { temp = p->fdsock; p->fdsock = -1; return temp; } } return -1; }/* * Check out the file descriptor for the requested connection. * Returns -1 if the connection is not found, other wise returns * the previously opened file descriptor. The CHECKED_OUT token * is left in the table to indicate that an application is * actively using the connection. */int pushcheckout(char* protocol, int port, char * store) { PushEntry *p; PushEntry *tmp; int fd; /* Find the entry to pass off the open file descriptor. */ for (p = pushlist; p != NULL ; p = tmp) { tmp = p->next; if (p->port == port && strncmp(p->value, protocol, strlen(protocol)) == 0) { /* Check if the current suite reserved the port. */ if (strcmp(store, p->storagename) != 0) { return -2; } fd = p->fd; p->state = CHECKED_OUT; return fd; } } return -1; }/* * Check in the file descriptor for the requested connection. * Returns 0 on success, or -1 on failure to check in the * file descriptor to the cached push registry. */int pushcheckin(int fd) { PushEntry *p; PushEntry *lastp = pushlist; PushEntry *tmp; /* Find the entry to pass off the open file descriptor. */ for (p = pushlist; p != NULL ; p = tmp) { tmp = p->next; if (p->fd == fd) { if (p->state == CHECKED_OUT) { pushcheckinentry(p); } return 0; } lastp = p ; } return -1; }/* * Check in the connections. Used between VM starts by main. */void pushcheckinall() { PushEntry *p; PushEntry *lastp = pushlist; PushEntry *tmp; /* Find the entry to pass off the open file descriptor. */ for (p = pushlist; p != NULL ; p = tmp) { tmp = p->next; pushcheckinentry(p); lastp = p ; }}/* * Check in the file descriptor connection for the requested connection, * given the connection name. * Returns 0 on success, or -1 on failure to check in the * file descriptor to the cached push registry. */int pushcheckinbyname(char* str) { PushEntry *p; PushEntry *lastp = pushlist; PushEntry *tmp; /* Find the entry to remove */ for (p = pushlist; p != NULL ; p = tmp) { tmp = p->next; if (strncmp (str, p->value, strlen(str)) == 0) { pushcheckinentry(p); return 0; } lastp = p ; } return -1; }/* * Check in the push entry and cleanup anything the MIDlet did not get. */static void pushcheckinentry(PushEntry *p) { p->state = CHECKED_IN; pushcleanupentry(p);}/* * Cleanup anything the MIDlet did not get. */static void pushcleanupentry(PushEntry *p) { /* Close any accepted socket not accessed, yet (if any). */ if (p->fdsock != -1) { prim_com_sun_midp_io_j2me_socket_Protocol_close0(p->fdsock); p->fdsock = -1; } /* Remove the cached datagram (if any). */ if (p->dg != NULL) { midpFree(p->dg); p->dg = NULL; }}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -