| version 1.7, 2002/10/21 00:37:00 | version 1.17, 2004/02/25 23:14:35 | 
|  |  | 
| /* $OpenXM: OpenXM/src/kan96xx/plugin/sm1Socket.c,v 1.6 2002/10/20 07:58:18 takayama Exp $ */ | /* $OpenXM: OpenXM/src/kan96xx/plugin/sm1Socket.c,v 1.16 2004/02/23 09:03:43 takayama Exp $ */ | 
| /* msg0s.c */ | /* msg0s.c */ | 
| #include <stdio.h> | #include <stdio.h> | 
| #include <sys/types.h> | #include <sys/types.h> | 
|  |  | 
| #include <sys/time.h> | #include <sys/time.h> | 
| #include <netinet/in.h> | #include <netinet/in.h> | 
| #include <netdb.h> | #include <netdb.h> | 
|  | #include <errno.h> | 
|  |  | 
|  |  | 
| #include "datatype.h" | #include "datatype.h" | 
|  |  | 
| #include "sm1Socket.h" | #include "sm1Socket.h" | 
|  |  | 
| extern int Quiet; | extern int Quiet; | 
|  | static int Post_debug=0; | 
| static void errorMsg1s(char *s); | static void errorMsg1s(char *s); | 
|  | static int getContentLength(char *s); | 
|  | static int getReceivedContentLength(char *s); | 
| #define MAX_LISTEN_QUEUE 3 | #define MAX_LISTEN_QUEUE 3 | 
|  |  | 
| /* [(sm1.socket) (open) [optional integer port, optional string name] ] extension ; */ | /* [(sm1.socket) (open) [optional integer port, optional string name] ] extension ; */ | 
| 
| Line 27  struct object KsocketOpen(struct object obj) { |  | 
| Line 31  struct object KsocketOpen(struct object obj) { |  | 
| int s_waiting; | int s_waiting; | 
| int on; | int on; | 
| int tt; | int tt; | 
| extern int errno; | extern int Post_debug; | 
|  |  | 
|  | if ((char *)getenv("OXWEB_DEBUG") != NULL) { | 
|  | Post_debug = 1; | 
|  | } | 
|  |  | 
| if (obj.tag != Sarray) { | if (obj.tag != Sarray) { | 
| errorMsg1s("KsocketOpen([optional integer,optional string name])"); | errorMsg1s("KsocketOpen([optional integer,optional string name])"); | 
| } | } | 
| 
| Line 171  struct object KsocketAccept(struct object obj) { |  | 
| Line 179  struct object KsocketAccept(struct object obj) { |  | 
| } | } | 
| s = KopInteger(obj1); | s = KopInteger(obj1); | 
| if ((news = accept(s,NULL,NULL)) < 0) { | if ((news = accept(s,NULL,NULL)) < 0) { | 
| errorMsg1s("Error in accept."); | fprintf(stderr,"Error in accept. Retrying (KsocketAccept).\n"); | 
|  | /* Code added for strange behavior on cygwin. */ | 
|  | if ((news = accept(s,NULL,NULL)) < 0) { | 
|  | errorMsg1s("Error in accept. Retry failed."); | 
|  | } | 
| } | } | 
| if (close(s) < 0) { | if (close(s) < 0) { | 
| errorMsg1s("Error in closing the old socket."); | errorMsg1s("Error in closing the old socket."); | 
| 
| Line 181  struct object KsocketAccept(struct object obj) { |  | 
| Line 193  struct object KsocketAccept(struct object obj) { |  | 
| return(robj); | return(robj); | 
| } | } | 
|  |  | 
|  | /* [ integer socketid ] | 
|  | [ integer newsocketid ] */ | 
|  | /* It does not close the listening socket. You can call it as | 
|  | ls = open. | 
|  | fd=accept2(ls).  close(fd). | 
|  | fd=accept2(ls).  close(fd). | 
|  | .... | 
|  | */ | 
|  | struct object KsocketAccept2(struct object obj) { | 
|  | struct object obj1; | 
|  | struct object obj2; | 
|  | struct object robj; | 
|  | int s, news; | 
|  |  | 
|  | if (obj.tag != Sarray) { | 
|  | errorMsg1s("KsocketAccept([integer socketid])"); | 
|  | } | 
|  | if (getoaSize(obj) < 1) { | 
|  | errorMsg1s("KsocketAccept([integer socketid])"); | 
|  | } | 
|  | obj1 = getoa(obj,0); | 
|  | if (obj1.tag != Sinteger ) { | 
|  | errorMsg1s("KsocketAccept([integer socketid]), argument must be integer."); | 
|  | } | 
|  | s = KopInteger(obj1); | 
|  | if ((news = accept(s,NULL,NULL)) < 0) { | 
|  | fprintf(stderr,"Error in accept. Retrying (KsocketAccept2).\n"); | 
|  | /* Code added for strange behavior on cygwin. */ | 
|  | if ((news = accept(s,NULL,NULL)) < 0) { | 
|  | errorMsg1s("Error in accept. Retry failed."); | 
|  | } | 
|  | } | 
|  | if (close(s) < 0) { | 
|  | errorMsg1s("Error in closing the old socket."); | 
|  | } | 
|  | robj = newObjectArray(1); | 
|  | putoa(robj,0,KpoInteger(news)); | 
|  | return(robj); | 
|  | } | 
|  |  | 
| int KsocketSelect0(int fd,int t) { | int KsocketSelect0(int fd,int t) { | 
| fd_set readfds; | fd_set readfds; | 
| struct timeval timeout; | struct timeval timeout; | 
| extern int errno; |  | 
| FD_ZERO(&readfds); | FD_ZERO(&readfds); | 
| FD_SET(fd,&readfds); | FD_SET(fd,&readfds); | 
| timeout.tv_sec = 0; | timeout.tv_sec = 0; | 
| 
| Line 250  struct object KsocketSelectMulti(struct object obj) |  | 
| Line 301  struct object KsocketSelectMulti(struct object obj) |  | 
| int size,i,fd,p,t; | int size,i,fd,p,t; | 
| fd_set readfds; | fd_set readfds; | 
| struct timeval timeout; | struct timeval timeout; | 
| extern errno; |  | 
| if (obj.tag != Sarray) { | if (obj.tag != Sarray) { | 
| errorMsg1s("KsocketSelectMulti([[sid1, sid2,...] optional integer timeout default 0]"); | errorMsg1s("KsocketSelectMulti([[sid1, sid2,...] optional integer timeout default 0]"); | 
| } | } | 
| 
| Line 361  struct object KsocketRead(struct object obj) { |  | 
| Line 411  struct object KsocketRead(struct object obj) { |  | 
| errorMsg1s("Select returns 1, but there is no data to read."); | errorMsg1s("Select returns 1, but there is no data to read."); | 
| } | } | 
| }else { /* increase the datasize */ | }else { /* increase the datasize */ | 
| tmp = (char *)GC_malloc(sizeof(char)*2*datasize); | tmp = (char *)sGC_malloc(sizeof(char)*2*datasize); | 
| /*I should use GC_malloc_atomic and free after finishing this function?*/ | /*I should use sGC_malloc_atomic and free after finishing this function?*/ | 
| if (tmp == (char *)NULL) errorMsg1s("Out of Memory."); | if (tmp == (char *)NULL) errorMsg1s("Out of Memory."); | 
| bcopy(data,tmp,totalsize); | bcopy(data,tmp,totalsize); | 
| data = tmp; | data = tmp; | 
| 
| Line 370  struct object KsocketRead(struct object obj) { |  | 
| Line 420  struct object KsocketRead(struct object obj) { |  | 
| } | } | 
| } | } | 
|  |  | 
| r = (char *)GC_malloc(sizeof(char)*(totalsize+1)); | r = (char *)sGC_malloc(sizeof(char)*(totalsize+1)); | 
| if (r == (char *)NULL) errorMsg1s("Out of Memory."); | if (r == (char *)NULL) errorMsg1s("Out of Memory."); | 
| bcopy(data,r,totalsize); | bcopy(data,r,totalsize); | 
| r[totalsize] = 0; | r[totalsize] = 0; | 
| 
| Line 532  struct object KsocketWriteByte(struct object obj) { |  | 
| Line 582  struct object KsocketWriteByte(struct object obj) { |  | 
| struct object KsocketReadHTTP(struct object socketObj) { | struct object KsocketReadHTTP(struct object socketObj) { | 
| /* Read until two empty line appears. */ | /* Read until two empty line appears. */ | 
| struct object ob; | struct object ob; | 
|  | struct object ob1; | 
|  | struct object nob; | 
| char *s; | char *s; | 
| char *sss; | char *sss; | 
| char *tmp; | char *tmp; | 
| 
| Line 540  struct object KsocketReadHTTP(struct object socketObj) |  | 
| Line 592  struct object KsocketReadHTTP(struct object socketObj) |  | 
| int flagmax = 1; | int flagmax = 1; | 
| int datasize; | int datasize; | 
| int last; | int last; | 
|  | int contentLength=-1; | 
|  | int socketid; | 
|  | extern int Post_debug; | 
|  | nob = NullObject; | 
|  |  | 
|  | if (socketObj.tag != Sarray) { | 
|  | errorMsg1s("KsocketReadHTTP([integer socketid])"); | 
|  | } | 
|  | if (getoaSize(socketObj) < 1) { | 
|  | errorMsg1s("KsocketReadHTTP([integer socketid])"); | 
|  | } | 
|  | ob1 = getoa(socketObj,0); | 
|  | if (ob1.tag != Sinteger) { | 
|  | errorMsg1s("KsocketReadHTTP([integer socketid]) : the argument must be integer."); | 
|  | } | 
|  | socketid = KopInteger(ob1); | 
|  |  | 
|  | if (KsocketSelect0(socketid,-1) != 1) { | 
|  | return(nob); | 
|  | } | 
| ob = KsocketRead(socketObj); | ob = KsocketRead(socketObj); | 
| s = KopString(ob); | s = KopString(ob); | 
| if (strncmp(s,"POST",4) == 0) flagmax=2; | if (strncmp(s,"POST",4) == 0) flagmax=2; /* for IE */ | 
| else flagmax=1; | else flagmax=1; | 
| flag = 0; | flag = 0; | 
| for (i=strlen(s)-1; i>=0; i--) { | for (i=strlen(s)-1; i>=0; i--) { | 
| 
| Line 565  struct object KsocketReadHTTP(struct object socketObj) |  | 
| Line 637  struct object KsocketReadHTTP(struct object socketObj) |  | 
| }else last = 0; | }else last = 0; | 
|  |  | 
| while (flag < flagmax) { | while (flag < flagmax) { | 
| fprintf(stderr,"Waiting in socketReadBlock (spin lock to wait an empty line). flagmax(0d,0a)=%d\n",flagmax); | contentLength = getContentLength(sss); | 
| if (strlen(s) == 0) {fprintf(stderr,"but I'm not receiving data. Expecting a bug.\n"); | if (contentLength != -1) { | 
|  | if (contentLength <= getReceivedContentLength(sss)) { | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (Post_debug) { | 
|  | fprintf(stderr,"Waiting in socketReadBlock. flagmax(0d,0a)=%d, content-length=%d, received content-length=%d\n",flagmax,contentLength,getReceivedContentLength(sss)); | 
|  | } | 
|  | if (strlen(s) == 0) { | 
|  | fprintf(stderr,"No data. Perhaps connection is closed by foreign host.\n"); | 
|  | return nob; | 
| }else{ | }else{ | 
| /* for debugging. */ | /* for debugging. */ | 
| for (i=0; i<strlen(sss); i++) { | if (Post_debug) { | 
| fprintf(stderr,"%3x",sss[i]); | for (i=0; i<strlen(sss); i++) { | 
|  | if ((sss[i] >= ' ') && (sss[i] < 0x7f)) { | 
|  | fprintf(stderr,"%c",sss[i]); | 
|  | }else{ | 
|  | fprintf(stderr,"(%3x)",sss[i]); | 
|  | if (sss[i] == 0xa) fprintf(stderr,"\n"); | 
|  | } | 
|  |  | 
|  | } | 
|  | fprintf(stderr,"\n"); | 
| } | } | 
| fprintf(stderr,"\n"); |  | 
| } | } | 
| sleep(2); |  | 
|  | if (KsocketSelect0(socketid,-1) != 1) { | 
|  | return nob; | 
|  | } | 
| ob = KsocketRead(socketObj); | ob = KsocketRead(socketObj); | 
| s = KopString(ob); | s = KopString(ob); | 
| for (i=strlen(s)-1; i>=0; i--) { | for (i=strlen(s)-1; i>=0; i--) { | 
| 
| Line 589  struct object KsocketReadHTTP(struct object socketObj) |  | 
| Line 682  struct object KsocketReadHTTP(struct object socketObj) |  | 
| } | } | 
| } | } | 
| if (datasize-1 <= strlen(sss)+strlen(s)) { | if (datasize-1 <= strlen(sss)+strlen(s)) { | 
| tmp = (char *)GC_malloc(sizeof(char)*2*(datasize+strlen(s))+1); | tmp = (char *)sGC_malloc(sizeof(char)*2*(datasize+strlen(s))+1); | 
| if (tmp == (char *)NULL) errorMsg1s("Out of Memory."); | if (tmp == (char *)NULL) errorMsg1s("Out of Memory."); | 
| strcpy(tmp,sss); | strcpy(tmp,sss); | 
| strcat(tmp,s); | strcat(tmp,s); | 
| 
| Line 618  struct object Kplugin_sm1Socket(char *key,struct objec |  | 
| Line 711  struct object Kplugin_sm1Socket(char *key,struct objec |  | 
| robj = KsocketConnect(obj); | robj = KsocketConnect(obj); | 
| }else if (strcmp(key,"accept") == 0) { | }else if (strcmp(key,"accept") == 0) { | 
| robj = KsocketAccept(obj); | robj = KsocketAccept(obj); | 
|  | }else if (strcmp(key,"accept2") == 0) { | 
|  | robj = KsocketAccept2(obj); | 
| }else if (strcmp(key,"select") == 0) { | }else if (strcmp(key,"select") == 0) { | 
| robj = KsocketSelect(obj); | robj = KsocketSelect(obj); | 
| }else if (strcmp(key,"mselect") == 0) { | }else if (strcmp(key,"mselect") == 0) { | 
| 
| Line 626  struct object Kplugin_sm1Socket(char *key,struct objec |  | 
| Line 721  struct object Kplugin_sm1Socket(char *key,struct objec |  | 
| robj = KsocketRead(obj); | robj = KsocketRead(obj); | 
| }else if (strcmp(key,"readHTTP") == 0) { | }else if (strcmp(key,"readHTTP") == 0) { | 
| robj = KsocketReadHTTP(obj); | robj = KsocketReadHTTP(obj); | 
|  | }else if (strcmp(key,"gethostname") == 0) { | 
|  | robj = KsocketGetHostName(); | 
| }else if (strcmp(key,"write") == 0) { | }else if (strcmp(key,"write") == 0) { | 
| robj = KsocketWrite(obj); | robj = KsocketWrite(obj); | 
| }else if (strcmp(key,"read") == 0) { | }else if (strcmp(key,"read") == 0) { | 
| 
| Line 643  struct object Kplugin_sm1Socket(char *key,struct objec |  | 
| Line 740  struct object Kplugin_sm1Socket(char *key,struct objec |  | 
| } | } | 
|  |  | 
|  |  | 
|  | static int getContentLength(char *s) { | 
|  | int n; | 
|  | int i,j; | 
|  | int len = -1; | 
|  | char *s1 = "content-length:"; | 
|  | char s0[256]; | 
|  | int m; | 
|  | m = strlen(s1); | 
|  | n = strlen(s); | 
|  | for (i=0; i<n; i++) { | 
|  | strncpy(s0,&(s[i]),m+1); | 
|  | for (j=0; j<m; j++) { | 
|  | if ((s0[j] >= 'A') && (s0[j] <= 'Z')) s0[j] = s0[j]+0x20; | 
|  | } | 
|  | if (strncmp(s0,s1,strlen(s1)) == 0) { | 
|  | sscanf(&(s[i+strlen(s1)]),"%d",&len); | 
|  | break; | 
|  | } | 
|  | } | 
|  | return len; | 
|  | } | 
|  | static int getReceivedContentLength(char *s) { | 
|  | int n; | 
|  | int i; | 
|  | int start; | 
|  | start = -1; | 
|  | n = strlen(s); | 
|  | for (i=0; i<n; i++) { | 
|  | if ((s[i] == '\n') && (s[i+1] == '\n')) { | 
|  | start = i+2; break; | 
|  | }else if ((s[i] == 0xd) && (s[i+1] == 0xa) && (s[i+2] == 0xd) && (s[i+3] == 0xa)) { | 
|  | start = i+4; | 
|  | } | 
|  | } | 
|  | if (start == -1) return 0; | 
|  | return (n-start); | 
|  | } | 
|  |  | 
|  |  | 
|  | struct object KsocketGetHostName(void) { | 
|  | char name[1024]; | 
|  | char *s; | 
|  | struct object rob = NullObject; | 
|  | if (gethostname(name,1023) != 0) { | 
|  | return rob; | 
|  | } | 
|  | s = (char *)sGC_malloc(sizeof(char)*(strlen(name)+2)); | 
|  | if (s == (char *)NULL) errorMsg1s("Out of Memory."); | 
|  | strcpy(s,name); | 
|  | return(KpoString(s)); | 
|  | } | 
|  |  | 
|  |  | 
|  |  |