📄 srvnet.c
字号:
for ( key=SHMKEY_BASE; key < SHMKEY_BASE+SHMKEY_MAX; key++ ) {
shmid = shmget(key,req->size,IPC_CREAT|IPC_EXCL|0666);
if ( shmid == -1 ) {
if ( errno != EEXIST )
goto bad;
} else {
tmp = shmat(shmid,0,0);
if ( tmp == (char *)-1 )
goto bad;
curclient->shm_cmds = tmp;
curclient->shm_cmds_shmid = shmid;
curclient->shm_cmds_size = req->size;
goto finish;
}
}
bad:
key = 0;
finish:
DPRINTF("Shm: Request key granted=%d\n",key);
GsWrite(current_fd, &key, sizeof(key));
#else
/* return no shared memory support*/
int key = 0;
GsWrite(current_fd, &key, sizeof(key));
#endif /* HAVE_SHAREDMEM_SUPPORT*/
}
static void
GrGetFontListWrapper(void *r)
{
MWFONTLIST **list;
int num;
int i, ttlen, mwlen;
GrGetFontList(&list, &num);
GsWriteType(current_fd, GrNumGetFontList);
/* the number of strings comming in */
GsWrite(current_fd, &num, sizeof(int));
if(num != -1) {
for(i = 0; i < num; i++) {
ttlen = strlen(list[i]->ttname) + 1;
mwlen = strlen(list[i]->mwname) + 1;
GsWrite(current_fd, &ttlen, sizeof(int));
GsWrite(current_fd, list[i]->ttname, ttlen * sizeof(char));
GsWrite(current_fd, &mwlen, sizeof(int));
GsWrite(current_fd, list[i]->mwname, mwlen * sizeof(char));
}
GrFreeFontList(&list, num);
}
}
void GrShmCmdsFlushWrapper(void *r);
/*
* Handler functions, ordered by reqType
*/
struct GrFunction {
void (*func)(void *);
GR_FUNC_NAME name;
} GrFunctions[] = {
/* 0 */ {GrOpenWrapper, "GrOpen"},
/* 1 */ {GrCloseWrapper, "GrClose"},
/* 2 */ {GrGetScreenInfoWrapper, "GrGetScreenInfo"},
/* 3 */ {GrNewWindowWrapper, "GrNewWindow"},
/* 4 */ {GrNewInputWindowWrapper, "GrNewInputWindow"},
/* 5 */ {GrDestroyWindowWrapper, "GrDestroyWindow"},
/* 6 */ {GrNewGCWrapper, "GrNewGC"},
/* 7 */ {GrCopyGCWrapper, "GrCopyGC"},
/* 8 */ {GrGetGCInfoWrapper, "GrGetGCInfo"},
/* 9 */ {GrDestroyGCWrapper, "GrDestroyGC"},
/* 10 */ {GrMapWindowWrapper, "GrMapWindow"},
/* 11 */ {GrUnmapWindowWrapper, "GrUnmapWindow"},
/* 12 */ {GrRaiseWindowWrapper, "GrRaiseWindow"},
/* 13 */ {GrLowerWindowWrapper, "GrLowerWindow"},
/* 14 */ {GrMoveWindowWrapper, "GrMoveWindow"},
/* 15 */ {GrResizeWindowWrapper, "GrResizeWindow"},
/* 16 */ {GrGetWindowInfoWrapper, "GrGetWindowInfo"},
/* 17 */ {GrGetFontInfoWrapper, "GrGetFontInfo"},
/* 18 */ {GrSetFocusWrapper, "GrSetFocus"},
/* 19 */ {GrSetWindowCursorWrapper, "GrSetWindowCursor"},
/* 20 */ {GrClearAreaWrapper, "GrClearAreaWrapper"},
/* 21 */ {GrSelectEventsWrapper, "GrSelectEvents"},
/* 22 */ {GrGetNextEventWrapper, "GrGetNextEvent"},
/* 23 */ {GrCheckNextEventWrapper, "GrCheckNextEvent"},
/* 24 */ {GrPeekEventWrapper, "GrPeekEvent"},
/* 25 */ {GrLineWrapper, "GrLine"},
/* 26 */ {GrPointWrapper, "GrPoint"},
/* 27 */ {GrRectWrapper, "GrRect"},
/* 28 */ {GrFillRectWrapper, "GrFillRect"},
/* 29 */ {GrPolyWrapper, "GrPoly"},
/* 30 */ {GrFillPolyWrapper, "GrFillPoly"},
/* 31 */ {GrEllipseWrapper, "GrEllipse"},
/* 32 */ {GrFillEllipseWrapper, "GrFillEllipse"},
/* 33 */ {GrSetGCForegroundWrapper, "GrSetGCForeground"},
/* 34 */ {GrSetGCBackgroundWrapper, "GrSetGCBackGround"},
/* 35 */ {GrSetGCUseBackgroundWrapper, "GrSetGCUseBackGround"},
/* 36 */ {GrSetGCModeWrapper, "GrSetGCMode"},
/* 37 */ {GrSetGCFontWrapper, "GrSetGCFont"},
/* 38 */ {GrGetGCTextSizeWrapper, "GrGetGCTextSize"},
/* 39 */ {GsReadAreaWrapper, "GsReadArea"},
/* 40 */ {GrAreaWrapper, "GrArea"},
/* 41 */ {GrBitmapWrapper, "GrBitmap"},
/* 42 */ {GrTextWrapper, "GrText"},
/* 43 */ {GrNewCursorWrapper, "GrNewCursor"},
/* 44 */ {GrMoveCursorWrapper, "GrMoveCursor"},
/* 45 */ {GrGetSystemPaletteWrapper, "GrGetSystemPalette"},
/* 46 */ {GrFindColorWrapper, "GrFindColor"},
/* 47 */ {GrReparentWindowWrapper, "GrReparentWindow"},
/* 48 */ {GrDrawImageFromFileWrapper, "GrDrawImageFromFile"},
/* 49 */ {GrLoadImageFromFileWrapper, "GrLoadImageFromFile"},
/* 50 */ {GrNewPixmapWrapper, "GrNewPixmap"},
/* 51 */ {GrCopyAreaWrapper, "GrCopyArea"},
/* 52 */ {GrSetFontSizeWrapper, "GrSetFontSize"},
/* 53 */ {GrCreateFontWrapper, "GrCreateFont"},
/* 54 */ {GrDestroyFontWrapper, "GrDestroyFont"},
/* 55 */ {GrReqShmCmdsWrapper, "GrReqShmCmds"},
/* 56 */ {GrShmCmdsFlushWrapper, "GrShmCmdsFlush"},
/* 57 */ {GrSetFontRotationWrapper, "GrSetFontRotation"},
/* 58 */ {GrSetFontAttrWrapper, "GrSetFontAttr"},
/* 59 */ {GrSetSystemPaletteWrapper, "GrSetSystemPalette"},
/* 60 */ {GrInjectEventWrapper, "GrInjectEvent"},
/* 61 */ {GrNewRegionWrapper, "GrNewRegion"},
/* 62 */ {GrDestroyRegionWrapper, "GrDestroyRegion"},
/* 63 */ {GrUnionRectWithRegionWrapper, "GrUnionRectWithRegion"},
/* 64 */ {GrUnionRegionWrapper, "GrUnionRegion"},
/* 65 */ {GrIntersectRegionWrapper, "GrIntersectRegion"},
/* 66 */ {GrSetGCRegionWrapper, "GrSetGCRegion"},
/* 67 */ {GrSubtractRegionWrapper, "GrSubtractRegion"},
/* 68 */ {GrXorRegionWrapper, "GrXorRegion"},
/* 69 */ {GrPointInRegionWrapper, "GrPointInRegion"},
/* 70 */ {GrRectInRegionWrapper, "GrRectInRegion"},
/* 71 */ {GrEmptyRegionWrapper, "GrEmptyRegion"},
/* 72 */ {GrEqualRegionWrapper, "GrEqualRegion"},
/* 73 */ {GrOffsetRegionWrapper, "GrOffsetRegion"},
/* 74 */ {GrGetRegionBoxWrapper, "GrGetRegionBox"},
/* 75 */ {GrNewPolygonRegionWrapper, "GrNewPolygonRegion"},
/* 76 */ {GrArcWrapper, "GrArc"},
/* 77 */ {GrArcAngleWrapper, "GrArcAngle"},
/* 78 */ {GrSetWMPropertiesWrapper, "GrSetWMProperties"},
/* 79 */ {GrGetWMPropertiesWrapper, "GrGetWMProperties"},
/* 80 */ {GrCloseWindowWrapper, "GrCloseWindow"},
/* 81 */ {GrKillWindowWrapper, "GrKillWindow"},
/* 82 */ {GrDrawImageToFitWrapper, "GrDrawImageToFit"},
/* 83 */ {GrFreeImageWrapper, "GrFreeImage"},
/* 84 */ {GrGetImageInfoWrapper, "GrGetImageInfo"},
/* 85 */ {GrDrawImageBitsWrapper, "GrDrawImageBits"},
/* 86 */ {GrPointsWrapper, "GrPoints"},
/* 87 */ {GrGetFocusWrapper, "GrGetFocus"},
/* 88 */ {GrGetSysColorWrapper, "GrGetSysColor"},
/* 89 */ {GrSetScreenSaverTimeoutWrapper, "GrSetScreenSaverTimeout"},
/* 90 */ {GrSetSelectionOwnerWrapper, "GrSetSelectionOwner"},
/* 91 */ {GrGetSelectionOwnerWrapper, "GrGetSelectionOwner"},
/* 92 */ {GrRequestClientDataWrapper, "GrRequestClientData"},
/* 93 */ {GrSendClientDataWrapper, "GrSendClientData"},
/* 94 */ {GrBellWrapper, "GrBell"},
/* 95 */ {GrSetBackgroundPixmapWrapper, "GrSetBackgroundPixmap"},
/* 96 */ {GrDestroyCursorWrapper, "GrDestroyCursor"},
/* 97 */ {GrQueryTreeWrapper, "GrQueryTree"},
/* 98 */ {GrCreateTimerWrapper, "GrCreateTimer"},
/* 99 */ {GrDestroyTimerWrapper, "GrDestroyTimer"},
/* 100 */ {GrSetPortraitModeWrapper, "GrSetPortraitMode"},
/* 101 */ {GrImageBufferAllocWrapper, "GrImageBufferAlloc"},
/* 102 */ {GrImageBufferSendWrapper, "GrImageBufferSend"},
/* 103 */ {GrLoadImageFromBufferWrapper, "GrLoadImageFromBuffer"},
/* 104 */ {GrDrawImageFromBufferWrapper, "GrDrawImageFromBuffer"},
/* 105 */ {GrGetFontListWrapper, "GrGetFontList"},
/* 106 */ {GrSetGCClipOriginWrapper, "GrSetGCClipOrigin"},
};
void
GrShmCmdsFlushWrapper(void *r)
{
nxShmCmdsFlushReq *req = r;
unsigned char reply;
#if HAVE_SHAREDMEM_SUPPORT
nxReq *pr;
int length;
unsigned char *do_req, *do_req_last;
if ( current_shm_cmds == 0 || current_shm_cmds_size < req->size ) {
/* No or short shm present serverside, bug or mischief */
EPRINTF("nano-X: Ill behaved client assumes shm ok\n");
if ( req->reply ) {
reply = 0;
GsWrite(current_fd, &reply, 1);
}
return;
}
do_req = current_shm_cmds;
do_req_last = current_shm_cmds + req->size;
while ( do_req < do_req_last ) {
pr = (nxReq *)do_req;
length = GetReqAlignedLen(pr);
if ( pr->reqType < GrTotalNumCalls ) {
GrFunctions[pr->reqType].func(pr);
} else {
EPRINTF("nano-X: Error bad shm function!\n");
}
do_req += length;
}
if ( req->reply ) {
reply = 1;
GsWrite(current_fd, &reply, 1);
}
#else
/* no shared memory support*/
if ( req->reply ) {
reply = 0;
GsWrite(current_fd, &reply, 1);
}
#endif /* HAVE_SHAREDMEM_SUPPORT*/
}
/*
* This function is used to bind to the named socket which is used to
* accept connections from the clients.
*/
int
GsOpenSocket(void)
{
#if ELKS
struct sockaddr_na sckt;
#ifndef SUN_LEN
#define SUN_LEN(ptr) (sizeof(sckt))
#endif
#elif __ECOS
struct sockaddr_in sckt;
#ifndef SUN_LEN
#define SUN_LEN(ptr) (sizeof(sckt))
#endif
#else
struct sockaddr_un sckt;
#ifndef SUN_LEN
#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \
+ strlen ((ptr)->sun_path))
#endif
#endif /* ELKS */
#if ELKS
if((un_sock = socket(AF_NANO, SOCK_STREAM, 0)) == -1)
return -1;
sckt.sun_family = AF_NANO;
sckt.sun_no = GR_NUMB_SOCKET;
#elif __ECOS
// Create the socket
if((un_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
return -1;
// Bind to any/all local IP addresses
memset( &sckt, '\0', sizeof(sckt) );
sckt.sin_family = AF_INET;
sckt.sin_len = sizeof(sckt);
sckt.sin_port = htons(6600);
sckt.sin_addr.s_addr = INADDR_ANY;
#else
if (access(GR_NAMED_SOCKET, F_OK) == 0) {
/* FIXME: should try connecting to see if server is active */
if(unlink(GR_NAMED_SOCKET))
return -1;
}
/* Create the socket: */
if((un_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
return -1;
/* Bind a name to the socket: */
sckt.sun_family = AF_UNIX;
strncpy(sckt.sun_path, GR_NAMED_SOCKET, sizeof(sckt.sun_path));
#endif /* ELKS */
if(bind(un_sock, (struct sockaddr *) &sckt, SUN_LEN(&sckt)) < 0)
return -1;
/* Start listening on the socket: */
if(listen(un_sock, 5) == -1)
return -1;
return 1;
}
void
GsCloseSocket(void)
{
if(un_sock != -1)
close(un_sock);
un_sock = -1;
unlink(GR_NAMED_SOCKET);
}
/*
* This function is used to accept a connnection from a client.
*/
void
GsAcceptClient(void)
{
int i;
#if ELKS
struct sockaddr_na sckt;
#elif __ECOS
struct sockaddr_in sckt;
#else
struct sockaddr_un sckt;
#endif
size_t size = sizeof(sckt);
if((i = accept(un_sock, (struct sockaddr *) &sckt, &size)) == -1) {
#ifdef __ECOS
// All ports should do this
EPRINTF("nano-X: Error accept failed (%s)\n", strerror(errno));
#else
EPRINTF("nano-X: Error accept failed (%d)\n", errno);
#endif
return;
}
GsAcceptClientFd(i);
}
/*
* This function accepts a client ID, and searches through the
* linked list of clients, returning a pointer to the relevant
* structure or NULL if not found.
*/
GR_CLIENT *
GsFindClient(int fd)
{
GR_CLIENT *client;
client = root_client;
while(client) {
if(client->id == fd)
return(client);
client = client->next;
}
return 0;
}
/*
* Destroy windows and eventclient structures used by client.
* Called by GsDropClient after a client has exited to clean
* up resources.
*/
void
GsDestroyClientResources(GR_CLIENT * client)
{
GR_WINDOW * wp, *nwp;
GR_PIXMAP * pp, *npp;
GR_GC * gp, *ngp;
GR_REGION * rp, *nrp;
GR_FONT * fp, *nfp;
GR_IMAGE * ip, *nip;
GR_CURSOR * cp, *ncp;
GR_EVENT_CLIENT *ecp, *necp;
GR_EVENT_CLIENT *pecp = NULL;
GR_EVENT_LIST *evp;
printf("Destroy client %d resources\n", client->id);
/* search window list, destroy windows owned by client*/
for(wp=listwp; wp; wp=nwp) {
nwp = wp->next;
/*
* Remove eventclient structures for this client
*/
ecp = wp->eventclients;
while (ecp) {
necp = ecp->next;
if (ecp->client == client) {
printf( " Destroy window %d eventclient mask %08lx\n", wp->id, ecp->eventmask);
if (ecp == wp->eventclients)
wp->eventclients = ecp->next;
else
pecp->next = ecp->next;
free(ecp);
} else
pecp = ecp;
ecp = necp;
}
if (wp->owner == client) {
printf(" Destroy window %d\n", wp->id);
GrDestroyWindow(wp->id);
}
}
/* search pixmap list, destroy pixmaps owned by client*/
for(pp=listpp; pp; pp=npp) {
npp = pp->next;
if (pp->owner == client) {
printf(" Destroy pixmap %d\n", pp->id);
GrDestroyWindow(pp->id);
}
}
/* free gc's owned by client*/
for(gp=listgcp; gp; gp=ngp) {
ngp = gp->next;
if (gp->owner == client) {
printf(" Destroy gc %d\n", gp->id);
GrDestroyGC(gp->id);
}
}
/* free fonts owned by client*/
for(fp=listfontp; fp; fp=nfp) {
nfp = fp->next;
if (fp->owner == client) {
printf(" Destroy font %d\n", fp->id);
GrDestroyFont(fp->id);
}
}
/* free regions owned by client*/
for(rp=listregionp; rp; rp=nrp) {
nrp = rp->next;
if (rp->owner == client) {
printf(" Destroy region %d\n", rp->id);
GrDestroyRegion(rp->id);
}
}
/* free images owned by client*/
for(ip=listimagep; ip; ip=nip) {
nip = ip->next;
if (ip->owner == client) {
printf(" Destroy image %d\n", ip->id);
GrFreeImage(ip->id);
}
}
/* free cursors owned by client*/
for(cp=listcursorp; cp; cp=ncp) {
ncp = cp->next;
if (cp->owner == client) {
printf(" Destroy cursor %d\n", cp->id);
GrDestroyCursor(cp->id);
}
}
/* Free events associated with client*/
evp = client->eventhead;
while (evp) {
printf(" Destroy event %d\n", evp->event.type);
client->eventhead = evp->next;
evp->next = eventfree;
eventfree = evp;
evp = client->eventhead;
}
}
/*
* Display window, pixmap, gc, font, region lists
*/
void
GsPrintResources(void)
{
GR_WINDOW *wp;
GR_PIXMAP *pp;
GR_GC *gp;
GR_REGION *rp;
GR_FONT *fp;
GR_IMAGE *ip;
/* window list*/
printf("Window list:\n");
for(wp=listwp; wp; wp=wp->next) {
printf("%d(%d),", wp->id, wp->owner? wp->owner->id: 0);
}
printf("\nPixmap list:\n");
for(pp=listpp; pp; pp=pp->next) {
printf("%d(%d),", pp->id, pp->owner->id);
}
printf("\nGC list:\n");
for(gp=listgcp; gp; gp=gp->next) {
printf("%d(%d),", gp->id, gp->owner->id);
}
printf("\nFont list:\n");
for(fp=listfontp; fp; fp=fp->next) {
printf("%d(%d),", fp->id, fp->owner->id);
}
printf("\nRegion list:\n");
for(rp=listregionp; rp; rp=rp->next) {
printf("%d(%d),", rp->id, rp->owner->id);
}
printf("\nImage list:\n");
for(ip=listimagep; ip; ip=ip->next) {
printf("%d(%d),", ip->id, ip->owner->id);
}
printf("\n");
}
/*
* This is used to drop a client when it is detected that the connection to it
* has been lost.
*/
void
GsDropClient(int fd)
{
GR_CLIENT *client;
if((client = GsFindClient(fd))) { /* If it exists */
close(fd); /* Close the socket */
GsDestroyClientResources(client);
if(client == root_client)
root_client = client->next;
/* Link the prev to the next */
if(client->prev) client->prev->next = client->next;
/* Link the next to the prev */
if(client->next) client->next->prev = client->prev;
#if HAVE_SHAREDMEM_SUPPORT
if ( client->shm_cmds != 0 ) {
/* Free shared memory */
shmctl(client->shm_cmds_shmid,IPC_RMID,0);
shmdt(client->shm_cmds);
}
#endif
GsPrintResources();
free(client); /* Free the structure */
clipwp = NULL; /* reset clip window*/
--connectcount;
} else EPRINTF("nano-X: trying to drop non-existent client %d.\n", fd);
}
/*
* This is a wrapper to read() which handles error conditions, and
* returns 0 for both error conditions and no data.
*/
int
#if ELKS
GsRead(int fd, char *buf, int c)
#else
GsRead(int fd, void *buf, int c)
#endif
{
int e, n;
n = 0;
while(n < c) {
e = read(fd, (buf + n), (c - n));
if(e <= 0) {
if (e == 0)
EPRINTF("nano-X: client closed socket: %d\n", fd);
else EPRINTF("nano-X: GsRead failed %d %d: %d\r\n",
e, n, errno);
GsClose(fd);
return -1;
}
n += e;
}
return 0;
}
/*
* This is a wrapper to write().
*/
int GsWrite(int fd, void *buf, int c)
{
int e, n;
n = 0;
while(n < c) {
e = write(fd, ((char *) buf + n), (c - n));
if(e <= 0) {
GsClose(fd);
return -1;
}
n += e;
}
return 0;
}
int GsWriteType(int fd, short type)
{
return GsWrite(fd,&type,sizeof(type));
}
/*
* This function is used to parse and dispatch requests from the clients.
* Note that the maximum request size is allocated from the stack
* in this function.
*/
void
GsHandleClient(int fd)
{
nxReq * req;
long len;
char buf[MAXREQUESTSZ];
current_fd = fd;
#if HAVE_SHAREDMEM_SUPPORT
current_shm_cmds = curclient->shm_cmds;
current_shm_cmds_size = curclient->shm_cmds_size;
#endif
/* read request header*/
if(GsRead(fd, buf, sizeof(nxReq)))
return;
len = GetReqAlignedLen((nxReq *)&buf[0]);
if(len > sizeof(nxReq)) {
if(len > MAXREQUESTSZ) {
EPRINTF("nano-X: GsHandleClient request too large: %ld > %d\n",
len, MAXREQUESTSZ);
exit(1);
}
/* read additional request data*/
if(GsRead(fd, &buf[sizeof(nxReq)], len-sizeof(nxReq)))
return;
}
req = (nxReq *)&buf[0];
if(req->reqType < GrTotalNumCalls) {
curfunc = GrFunctions[req->reqType].name;
/*DPRINTF("HandleClient %s\n", curfunc);*/
GrFunctions[req->reqType].func(req);
} else {
EPRINTF("nano-X: GsHandleClient bad function\n");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -