static int module_do_callback_(const struct cbmod_st* cbmod, struct jbxm_callback_if_st* cbif) { FUNC_ENTER JBX_ASSERT(cbmod); struct type2cb_st t2cb = { 0 }; syserr = type2cb(cbif->type, cbmod->loadlib_ref->callbacks, &t2cb); if (syserr) { FIRE("type2cb"); } if (! t2cb.func) { FINISH(); } cbif->process_no = mgd.runv.ss.nt_boottime; TRCLOG( "enter user-function\n" "--->>\n" "\t dll path = %s\n" "\t func name = %s (%p)\n" "\t next events = 0x%08x%s" , cbmod->iconf->dllpath , t2cb.name , t2cb.func , cbif->flow ? (cbif->flow->next_events) : 0 , cbif->flow ? (cbif->flow->next_events ? " *" : "") : "" ); syserr = t2cb.func(cbmod->iconf, cbif); if (syserr) { FIRE("callback(type=%d)", cbif->type); } TRCLOG( "leave user-function\n" "\t dll path = %s\n" "\t func name = %s (%p)\n" "\t next events = 0x%08x%s\n" "<<---" , cbmod->iconf->dllpath , t2cb.name , t2cb.func , cbif->flow ? (cbif->flow->next_events) : 0 , cbif->flow ? (cbif->flow->next_events ? " *" : "") : "" ); FUNC_CHECKPOINT FUNC_LEAVE return FUNC_RC_INT(); }
static void t_wait(void *a) { hal_set_current_thread_priority( THREAD_PRIO_HIGH ); char *name = a; while(!thread_stop_request) { thread_activity_counter++; if(TEST_CHATTY) printf("--- thread %s will wait 4 cond ---\n", name); hal_mutex_lock(&m); checkEnterMutex(); checkLeaveMutex(); hal_cond_wait(&c, &m); checkEnterMutex(); checkLeaveMutex(); hal_mutex_unlock(&m); if(TEST_CHATTY) printf("--- thread %s runs ---\n", name); //pressEnter("--- thread a runs ---\n"); YIELD(); } FINISH(); }
static int timer_handler(sd_event_source *es, uint64_t usec, void *vmpid) { (void)es; (void)usec; (void)vmpid; FINISH(POE_TIMEDOUT, -1, NULL); return 0; }
static int sigint_handler(sd_event_source *es, const struct signalfd_siginfo *si, void *vmpid) { (void)es; (void)si; (void)vmpid; FINISH(POE_TIMEDOUT, -1, "Supervisor terminated"); return 0; }
/* * Main interpreter loop. * * This was written with an ARM implementation in mind. */ void dvmInterpretPortable(Thread* self) { #if defined(EASY_GDB) StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame); #endif DvmDex* methodClassDex; // curMethod->clazz->pDvmDex JValue retval; /* core state */ const Method* curMethod; // method we're interpreting const u2* pc; // program counter u4* fp; // frame pointer u2 inst; // current instruction /* instruction decoding */ u4 ref; // 16 or 32-bit quantity fetched directly u2 vsrc1, vsrc2, vdst; // usually used for register indexes /* method call setup */ const Method* methodToCall; bool methodCallRange; /* static computed goto table */ DEFINE_GOTO_TABLE(handlerTable); /* copy state in */ curMethod = self->interpSave.method; pc = self->interpSave.pc; fp = self->interpSave.curFrame; retval = self->interpSave.retval; /* only need for kInterpEntryReturn? */ methodClassDex = curMethod->clazz->pDvmDex; LOGVV("threadid=%d: %s.%s pc=%#x fp=%p", self->threadId, curMethod->clazz->descriptor, curMethod->name, pc - curMethod->insns, fp); /* * Handle any ongoing profiling and prep for debugging. */ if (self->interpBreak.ctl.subMode != 0) { TRACE_METHOD_ENTER(self, curMethod); self->debugIsMethodEntry = true; // Always true on startup } /* * DEBUG: scramble this to ensure we're not relying on it. */ methodToCall = (const Method*) -1; #if 0 if (self->debugIsMethodEntry) { ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor, curMethod->name); DUMP_REGS(curMethod, self->interpSave.curFrame, false); } #endif FINISH(0); /* fetch and execute first instruction */
static int sigchld_handler(sd_event_source *es, const struct signalfd_siginfo *si, void *vmpid) { (void)es; pid_t mpid = *(pid_t *)vmpid; if (si->ssi_signo != SIGCHLD) ERROR("parent: unexpected signal"); while (true) { int status; pid_t spid = waitpid(-mpid, &status, WNOHANG | __WALL); NONNEGATIVE(spid); if (!spid) break; if (WIFEXITED(status) && spid == mpid) { FINISH(POE_SUCCESS, WEXITSTATUS(status), NULL); } else if (WIFSIGNALED(status) && spid == mpid) { FINISH(POE_SIGNALED, -1, "Program terminated with signal %d (%s)", WTERMSIG(status), strsignal(WTERMSIG(status))); } else if (WIFSTOPPED(status)) { int e = status >> 16 & 0xff; switch (e) { case PTRACE_EVENT_SECCOMP: handle_syscall(spid); break; case PTRACE_EVENT_CLONE: case PTRACE_EVENT_FORK: case PTRACE_EVENT_VFORK: ptrace(PTRACE_CONT, spid, 0, 0); break; default: ptrace(PTRACE_CONT, spid, 0, WSTOPSIG(status)); break; } } } return 0; }
static void handle_syscall(pid_t pid) { errno = 0; int syscalln = ptrace(PTRACE_PEEKUSER, pid, sizeof(long) * ORIG_RAX); if (errno) ERROR("ptrace(PTRACE_PEEKUSER) failed"); switch (syscalln) { default: goto kill; } kill: kill(pid, SIGKILL); char *rule = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, syscalln); if (!rule) ERROR("seccomp_syscall_resolve_num_arch() failed"); FINISH(POE_SIGNALED, -1, "System call %s is blocked", rule); allowed: ptrace(PTRACE_CONT, pid, 0, 0); }
static void thread1(void *a) { char *name = a; while(!thread_stop_request) { thread_activity_counter++; if(TEST_CHATTY) printf("--- thread %s runs ---\n", name); pressEnter(""); if(TEST_CHATTY) printf("Will lock mutex\n"); hal_mutex_lock(&m); if(TEST_CHATTY) printf("locked mutex\n"); checkEnterMutex(); YIELD(); if(TEST_CHATTY) printf("Will unlock mutex\n"); checkLeaveMutex(); hal_mutex_unlock(&m); if(TEST_CHATTY) printf("unlocked mutex\n"); if( random() & 1 ) hal_sem_acquire( &s ); counter++; if(counter >7) { counter = 0; if(TEST_CHATTY) printf("Will signal cond\n"); hal_cond_signal(&c); if(TEST_CHATTY) printf("Signalled cond\n"); } YIELD(); } FINISH(); }
/* * Main interpreter loop. * * This was written with an ARM implementation in mind. */ bool INTERP_FUNC_NAME(Thread* self, InterpState* interpState) { #if defined(EASY_GDB) StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->curFrame); #endif #if INTERP_TYPE == INTERP_DBG bool debugIsMethodEntry = interpState->debugIsMethodEntry; #endif #if defined(WITH_TRACKREF_CHECKS) int debugTrackedRefStart = interpState->debugTrackedRefStart; #endif DvmDex* methodClassDex; // curMethod->clazz->pDvmDex JValue retval; /* core state */ const Method* curMethod; // method we're interpreting const u2* pc; // program counter u4* fp; // frame pointer u2 inst; // current instruction /* instruction decoding */ u2 ref; // 16-bit quantity fetched directly u2 vsrc1, vsrc2, vdst; // usually used for register indexes /* method call setup */ const Method* methodToCall; bool methodCallRange; #if defined(THREADED_INTERP) /* static computed goto table */ DEFINE_GOTO_TABLE(handlerTable); #endif #if defined(WITH_JIT) #if 0 LOGD("*DebugInterp - entrypoint is %d, tgt is 0x%x, %s\n", interpState->entryPoint, interpState->pc, interpState->method->name); #endif #if INTERP_TYPE == INTERP_DBG /* Check to see if we've got a trace selection request. */ if ( /* * Only perform dvmJitCheckTraceRequest if the entry point is * EntryInstr and the jit state is either kJitTSelectRequest or * kJitTSelectRequestHot. If debugger/profiler happens to be attached, * dvmJitCheckTraceRequest will change the jitState to kJitDone but * but stay in the dbg interpreter. */ (interpState->entryPoint == kInterpEntryInstr) && (interpState->jitState == kJitTSelectRequest || interpState->jitState == kJitTSelectRequestHot) && dvmJitCheckTraceRequest(self, interpState)) { interpState->nextMode = INTERP_STD; //LOGD("Invalid trace request, exiting\n"); return true; } #endif /* INTERP_TYPE == INTERP_DBG */ #endif /* WITH_JIT */ /* copy state in */ curMethod = interpState->method; pc = interpState->pc; fp = interpState->fp; retval = interpState->retval; /* only need for kInterpEntryReturn? */ methodClassDex = curMethod->clazz->pDvmDex; LOGVV("threadid=%d: entry(%s) %s.%s pc=0x%x fp=%p ep=%d\n", self->threadId, (interpState->nextMode == INTERP_STD) ? "STD" : "DBG", curMethod->clazz->descriptor, curMethod->name, pc - curMethod->insns, fp, interpState->entryPoint); /* * DEBUG: scramble this to ensure we're not relying on it. */ methodToCall = (const Method*) -1; #if INTERP_TYPE == INTERP_DBG if (debugIsMethodEntry) { ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor, curMethod->name); DUMP_REGS(curMethod, interpState->fp, false); } #endif switch (interpState->entryPoint) { case kInterpEntryInstr: /* just fall through to instruction loop or threaded kickstart */ break; case kInterpEntryReturn: CHECK_JIT(); goto returnFromMethod; case kInterpEntryThrow: goto exceptionThrown; default: dvmAbort(); } #ifdef THREADED_INTERP FINISH(0); /* fetch and execute first instruction */ #else while (1) { CHECK_DEBUG_AND_PROF(); /* service debugger and profiling */ CHECK_TRACKED_REFS(); /* check local reference tracking */ /* fetch the next 16 bits from the instruction stream */ inst = FETCH(0); switch (INST_INST(inst)) {
static void rundaemon(srs_t *srs, char *path, int daemonflags) { fd_set readfds_sv; fd_set readfds; struct sockaddr_un addr; socklen_t addrlen; int sock; int maxfd; int fd; char line[BUFSIZ]; int len; char buf[BUFSIZ]; char *cp; char *address; char *alias; int ret; sock = listen_socket(path); /* daemon() */ FD_ZERO(&readfds_sv); FD_SET(sock, &readfds_sv); maxfd = sock + 1; #define FINISH(fd) \ do { close(fd); FD_CLR(fd, &readfds_sv); continue; } while(0) #define SKIPWHITE(cp) while (isspace(*cp)) cp++; if (!(daemonflags & DF_NOFORK)) { if (daemon(0, 0) < 0) perror("daemon"); } for (;;) { memcpy(&readfds, &readfds_sv, sizeof(fd_set)); select(maxfd, &readfds, NULL, NULL, NULL); for (fd = 0; fd < maxfd; fd++) { if (FD_ISSET(fd, &readfds)) { if (fd == sock) { fd = accept(sock, (struct sockaddr*)&addr,&addrlen); if (fd < 0) { perror("accept"); continue; } FD_SET(fd, &readfds_sv); if (fd >= maxfd) maxfd = fd + 1; fprintf(stderr, "Accept %d\n", fd); continue; } else { len = read(fd, line, BUFSIZ); if (len <= 0) { if (len < 0) perror("read"); fprintf(stderr, "Close %d\n", fd); FINISH(fd); } line[strcspn(line, "\r\n")] = '\0'; fprintf(stderr, "%d: %s\n", fd, line); if (strncasecmp(line, "forward ", 8) == 0) { cp = line + 8; while (isspace(*cp)) cp++; address = cp; cp = strchr(address, ' '); if (cp == NULL) { fprintf(stderr, "No alias in %s on %d\n", line, fd); FINISH(fd); } *cp++ = '\0'; while (isspace(*cp)) cp++; alias = cp; ret = srs_forward(srs, buf, BUFSIZ, address, alias); if (ret != SRS_SUCCESS) { fprintf(stderr, "SRS error: %s\n", srs_strerror(ret)); FINISH(fd); } fprintf(stderr, "Forward %s, %s -> %s\n", address, alias, buf); write(fd, buf, strlen(buf)); write(fd, "\n", 1); FINISH(fd); } else if (strncasecmp(line, "reverse ", 8) == 0) { cp = line + 8; while (isspace(*cp)) cp++; address = cp; ret = srs_reverse(srs, buf, BUFSIZ, address); if (ret != SRS_SUCCESS) { fprintf(stderr, "SRS error: %s\n", srs_strerror(ret)); FINISH(fd); } fprintf(stderr, "Reverse %s -> %s\n", address, buf); write(fd, buf, strlen(buf)); write(fd, "\n", 1); FINISH(fd); } else { fprintf(stderr, "Unknown command %s on %d\n", line, fd); FINISH(fd); } } } } } }
/* * Main interpreter loop. * * This was written with an ARM implementation in mind. * portable���͵Ľ������Ľ���ѭ����� */ void dvmInterpretPortable(Thread* self) { #if defined(EASY_GDB) // ��������Ƿ�����ԣ�������ջ֡�ĵ�ַ StackSaveArea* debugSaveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame); #endif DvmDex* methodClassDex; // curMethod->clazz->pDvmDex JValue retval; /* core state */ const Method* curMethod; // method we're interpreting ��ǰ����Ҫ���͵ķ��� const u2* pc; // program counter ��������� u4* fp; // frame pointer ָ֡�� u2 inst; // current instruction ��ǰָ�� /* instruction decoding */ u4 ref; // 16 or 32-bit quantity fetched directly u2 vsrc1, vsrc2, vdst; // usually used for register indexes /* method call setup */ const Method* methodToCall; bool methodCallRange; /* * static computed goto table * ��̬����õ���ת�� * ʵ���Ͼ��Ƕ���õ�һ����� * �þ�̬��ת����libdex��dexopcode.h�ж��� * [��Ҫע����壺�ñ�ֻ�ṩ����cʵ�ֵĽ�������ʹ��] * ������������ * static const void* handlerTable[0x100] = { \ * H(OP_NOP), \ * H(OP_MOVE), \ * .... * } * ���������opcode-gen������߶�̬���ɵģ�����˵�����������ʲô�����ɵģ���Ҫ�ο��ù��ߵ�ʵ�� * * # define H(_op) &&op_##_op * ʵ�����������������&&op_OP_NOP �����ĵ�ַ */ DEFINE_GOTO_TABLE(handlerTable); /* copy state in * ��ʼ��һЩ״ֵ̬ */ curMethod = self->interpSave.method; pc = self->interpSave.pc; fp = self->interpSave.curFrame; retval = self->interpSave.retval; /* only need for kInterpEntryReturn? */ methodClassDex = curMethod->clazz->pDvmDex; //��ȡdex��ص�����(������Ҫ�ο�vm\DvmDex.cpp��������ʵ��) LOGVV("threadid=%d: %s.%s pc=%#x fp=%p", self->threadId, curMethod->clazz->descriptor, curMethod->name, pc - curMethod->insns, fp); /* * Handle any ongoing profiling and prep for debugging. * ������Ҫ�Ƿ�����ԣ�����������һ�����巽���Ľ��� */ if (self->interpBreak.ctl.subMode != 0) { TRACE_METHOD_ENTER(self, curMethod); self->debugIsMethodEntry = true; // Always true on startup } /* * DEBUG: scramble this to ensure we're not relying on it. */ methodToCall = (const Method*) -1; #if 0 if (self->debugIsMethodEntry) { ILOGD("|-- Now interpreting %s.%s", curMethod->clazz->descriptor, curMethod->name); DUMP_REGS(curMethod, self->interpSave.curFrame, false); } #endif //�����↑ʼ����ȡָ�ִ�У����صĽ� // ������ʵ���Ͻ�����һ��do - while��ѭ����ֱ��ִ����Ϸ��� FINISH(0); /* fetch and execute first instruction */
bool handle(int csock) { NOTICE("################# REQUEST"); PGconn *cnxn = NULL; char buf[BUF_LEN + 2]; buf[0] = 0; DEFINE_VAR_ALL(str_response, str_request, str_uri, str_temp, str_form_data); DEFINE_VAR_MORE(str_correct_referer_start1, str_correct_referer_start2); DEFINE_VAR_MORE(str_referer, str_host, str_request_len, str_boundary); DEFINE_VAR_MORE(str_cookie_envelope, str_complete_response, str_buffer); DEBUG("### get the str_request\n"); //########################################## //### get the str_request //DEBUG(">%d|%d<", SSIZE_MAX, BUF_LEN); int int_request_len = BUF_LEN; memset(buf, 0, BUF_LEN + 1); int_request_len = read(csock, buf, BUF_LEN); FINISH_SALLOC(str_request, int_request_len + 1); memcpy(str_request, buf, int_request_len); str_request[int_request_len] = '\0'; //HERE BE DRAGONS //Maintainer: joseph //This code reads from the socket only for as long as is necessary. //If we have just one extra read command, it will hang until the browser //sends more data. Which it won't. So read until end of request. //@@@@@@@@@@@@@@@@@@@@@**^^""~~~"^@@^*@*@@**@@@@@@@@@ //@@@@@@@@@@@@@*^^'"~ , - ' '; ,@@b. ' -e@@@@@@@@@ //@@@@@@@@*^"~ . ' . ' ,@@@@( e@*@@@@@@@@@@ //@@@@@^~ . . ' @@@@@@, ~^@@@@@@@@@@@ //@@@~ ,e**@@*e, ,e**e, . ' '@@@@@@e, "*@@@@@'^@ //@',e@@@@@@@@@@ e@@@@@@ ' '*@@@@@@ @@@' 0 //@@@@@@@@@@@@@@@@@@@@@',e, ; ~^*^' ;^~ ' 0 //@@@@@@@@@@@@@@@^""^@@e@@@ .' ,' .' @ //@@@@@@@@@@@@@@' '@@@@@ ' , ,e' . ;@ //@@@@@@@@@@@@@' ,&&, ^@*' , . i^"@e, ,e@e @@ //@@@@@@@@@@@@' ,@@@@, ; ,& !,,@@@e@@@@ e@@ //@@@@@,~*@@*' ,@@@@@@e, ', e^~^@, ~'@@@@@@,@@@ //@@@@@@, ~" ,e@@@@@@@@@*e*@* ,@e @@""@e,,@@@@@@@@@ //@@@@@@@@ee@@@@@@@@@@@@@@@" ,e@' ,e@' e@@@@@@@@@@@@@ //@@@@@@@@@@@@@@@@@@@@@@@@" ,@" ,e@@e,,@@@@@@@@@@@@@@ //@@@@@@@@@@@@@@@@@@@@@@@~ ,@@@,,0@@@@@@@@@@@@@@@@@@@ //@@@@@@@@@@@@@@@@@@@@@@@@,,@@@@@@@@@@@@@@@@@@@@@@@@@ //""""""""""""""""""""""""""""""""""""""""""""""""""" char *ptr_boundary_start = strstr(str_request, "Content-Type: multipart/form-data; boundary="); if (ptr_boundary_start != NULL && strchr(ptr_boundary_start, 13) == NULL) { memset(buf, 0, BUF_LEN + 1); int int_current_length = read(csock, buf, BUF_LEN); FINISH_SREALLOC(str_request, int_current_length + int_request_len + 1); memcpy(str_request + int_request_len, buf, int_current_length); str_request[int_current_length + int_request_len] = '\0'; int_request_len = int_request_len + int_current_length; } //DEBUG("test0>%s|%i<", str_request, int_request_len); char *request_ptr; //// ****if upload then special case if (strstr(str_request, "Content-Type: multipart/form-data; boundary=") != 0) { //get boundary char *boundary_ptr = strstr(str_request, "Content-Type: multipart/form-data; boundary=") + 44; char *boundary_end_ptr = strchr(boundary_ptr, 13) != 0 ? strchr(boundary_ptr, 13) : strchr(boundary_ptr, 10); DEBUG("str_boundary: %d %d", boundary_end_ptr, boundary_ptr); int int_boundary_length = boundary_end_ptr - boundary_ptr; DEBUG("str_boundary: %d", int_boundary_length); FINISH_SALLOC(str_boundary, int_boundary_length + 3); //extra and null byte DEBUG("TESTING1"); memcpy(str_boundary, boundary_ptr, int_boundary_length); DEBUG("TESTING2"); str_boundary[int_boundary_length + 0] = '-'; DEBUG("TESTING3"); str_boundary[int_boundary_length + 1] = '-'; DEBUG("TESTING4"); str_boundary[int_boundary_length + 2] = '\0'; DEBUG("TESTING5"); int int_current_length = BUF_LEN; DEBUG("TESTING6"); //DEBUG("str_boundary: %s", str_boundary); //DEBUG("str_request: %s", str_request); DEBUG("bstrstr(\"%-10s\", %d, \"%s\", %d", str_request, int_request_len, str_boundary, int_boundary_length + 2); /* DEBUG("test0>%s<", bstrstr( str_request, int_request_len, str_boundary, int_boundary_length + 2) == NULL ? "NULL" : "NOT NULL"); while (bstrstr( str_request, int_request_len, str_boundary, int_boundary_length + 2) == NULL) {//while null DEBUG("test1"); memset(buf, 0, BUF_LEN + 1); //FINISH_SALLOC(str_buffer, BUF_LEN + 2); DEBUG("test2"); int_current_length = read(csock, buf, BUF_LEN); DEBUG("test3"); FINISH_SREALLOC(str_request, int_request_len + int_current_length + 1); DEBUG("test4>%s<", str_request); memcpy(str_request + int_request_len, buf, int_current_length); int_request_len = int_request_len + int_current_length; str_request[int_request_len] = '\0'; //SFREE(str_buffer); DEBUG("test5>%i<", int_request_len); } */ DEBUG(">%s<", bstrstr( str_request + int_request_len - int_current_length - int_boundary_length, int_current_length + int_boundary_length, str_boundary, int_boundary_length + 2) == NULL ? "NULL" : "NOT NULL"); while (bstrstr( str_request + int_request_len - int_current_length - int_boundary_length, int_current_length + int_boundary_length, str_boundary, int_boundary_length + 2) == NULL) {//while null memset(buf, 0, BUF_LEN + 1); //DEBUG("test1"); int_current_length = read(csock, buf, BUF_LEN); //DEBUG("test2"); FINISH_SREALLOC(str_request, int_request_len + int_current_length + 1); //DEBUG("test3>%s<", str_request); memcpy(str_request + int_request_len, buf, int_current_length); int_request_len = int_request_len + int_current_length; str_request[int_request_len] = '\0'; //DEBUG("test4>%i<", int_request_len); } DEBUG("test5>%s<", bstrstr( str_request, int_request_len, str_boundary, int_boundary_length + 2) - 25); SFREE(str_boundary); //// **** // if post or put, then get content length and receive that amount after two newlines, then break } else if (strncmp(str_request, "P", 1) == 0) { //we need Content-Length: before we can continue while (! strstr(str_request, "Content-Length:")) { memset(buf, 0, BUF_LEN + 1); //DEBUG("test1"); int_request_len = read(csock, buf, BUF_LEN); //DEBUG("test2>%i<", int_request_len); //buf[request_len] = 0; FINISH_CAT_APPEND(str_request, buf); //DEBUG("#request_len:%d", int_request_len); } request_ptr = strstr(str_request, "Content-Length:"); // if we didn't find anything we need to stop, len("Content-Length")==15 if (strlen(request_ptr) < 16) { // error bad str_request FINISH("Bad str_request"); } // move pointer to start of content length value request_ptr = request_ptr + 15; //DEBUG("request_ptr>%s<", request_ptr); // step through the buffer and see if we can get the length int req_len = 0; while (request_ptr != 0 && *request_ptr != '\r' && *request_ptr != '\n') { if (request_ptr == 0 && req_len == 0) { // error bad str_request } //do not comment next line!!!!!!!! give inconsistent output without this line!!!!!! idk why!!!!!!! //DEBUG("test1>%c<", *request_ptr); /////////////// if (*request_ptr != '\r' && *request_ptr != '\n') { request_ptr = request_ptr + 1; req_len = req_len + 1; } } FINISH_SALLOC(str_request_len, req_len + 1); request_ptr = request_ptr - req_len; memcpy(str_request_len, request_ptr, req_len); str_request_len[req_len] = '\0'; //DEBUG("test2>%s|%s<", str_request_len, request_ptr, req_len); req_len = atoi(str_request_len); SFREE(str_request_len); while (strstr(str_request,"\r\n\r\n") == 0 && strstr(str_request, "\n\n") == 0 && strstr(str_request, "\r\r") == 0) { memset(buf,0,BUF_LEN + 1); int_request_len = read(csock, buf, BUF_LEN); FINISH_CAT_APPEND(str_request, buf); } request_ptr = strstr(str_request,"\r\n\r\n") != 0 ? strstr(str_request,"\r\n\r\n") + 4 : strstr(str_request,"\n\n") != 0 ? strstr(str_request,"\n\n") + 2 : strstr(str_request,"\r\r") != 0 ? strstr(str_request,"\r\r") + 2 : 0; unsigned int int_length_we_want = ((request_ptr - str_request) + req_len); //DEBUG("test3>%s|%s<", str_request, request_ptr); //DEBUG("test4>%i|%i|%i|%i<\n", int_length_we_want, strlen( str_request ), (request_ptr - str_request), req_len); while (int_length_we_want > strlen(str_request)) { memset(buf,0,BUF_LEN + 1); int_request_len = read(csock, buf, BUF_LEN); FINISH_CAT_APPEND(str_request, buf); //DEBUG("test4.1>%i|%i<\n", int_length_we_want, strlen( str_request )); } //DEBUG("test5\n"); int_request_len = strlen(str_request); // if not POST, then break at two newlines. // (only other request we accept is GET, we don't use any other methods of request) } else { while (strstr(str_request,"\r\n\r\n") == 0 && strstr(str_request,"\n\n") == 0 && strstr(str_request,"\r\r") == 0) { memset(buf, 0, BUF_LEN + 1); int_request_len = read(csock, buf, BUF_LEN); FINISH_CAT_APPEND(str_request, buf); } int_request_len = strlen(str_request); } DEBUG("request_len>%i<", strlen(str_request)); /* //for testing actions GS.ajaxJSON('URI', 'PARAMS', function (data, error) { if (!error) { console.log(data); } else { GS.ajaxErrorDialog(data); } }); */ str_uri = str_uri_path(str_request); FINISH_CHECK(str_uri != NULL, "str_uri_path failed"); INFO("### str_uri: %s", str_uri); str_host = request_header(str_request, "host"); INFO("### str_host: %s", str_host); //DEBUG("### REQUEST: %s", str_request); //check referer str_referer = request_header(str_request, "Referer"); INFO("### str_referer: %s", str_referer); //when we have a referer, we should make sure it matches our website, but we have a few exceptions. if (str_referer != NULL) { FINISH_CAT_CSTR(str_correct_referer_start1, "https://", str_host); FINISH_CAT_CSTR(str_correct_referer_start2, "http://" , str_host); FINISH_CHECK( strncmp(str_correct_referer_start1, str_referer, strlen(str_correct_referer_start1)) == 0 || strncmp(str_correct_referer_start2, str_referer, strlen(str_correct_referer_start2)) == 0 || strlen(str_referer) <= 0 || strncmp(str_uri, "/v1/" , 4 ) != 0 || //strncmp(str_uri, "/v1/env/auth", 12) == 0 || strncmp(str_uri, "/v1/cluster" , 11) == 0 || strncmp(str_uri, "/v1/app" , 7 ) == 0 || strncmp(str_uri, "/v1/dev" , 7 ) == 0, "Referer does not match host."); SFREE(str_correct_referer_start1); SFREE(str_correct_referer_start2); } //#################################################################################################### //######################################### MANAGE COOKIES ########################################### // set up database connection // FEAR NOT GCC! This will not be used uninitialized. //PQinitOpenSSL(0, 0); //prevent Libpq from initializing ssl bool bol_valid_subdomain = false; //if subdomain database configuration is active, then change int_global_current_conn_port //we use int_global_current_conn_port to connect to the postgres instance //if the subdomain is the default subdomain, we should connect to production //if the subdomain is not the default subdomain, we should connect to the correct developer area //if the subdomain is not recognized, we should connect to production if (strlen(str_global_developers) > 0) { char *temp = strchr(str_host, '.'); int int_length = temp - str_host; FINISH_SALLOC(str_current_subdomain, int_length + 1); DEBUG("### str_host: %s, temp: %s, char: %c, int_length: %d\n", str_host, temp, '.', int_length); memcpy(str_current_subdomain, str_host, int_length); str_current_subdomain[int_length] = '\0'; str_temp = getport(str_global_developers, str_current_subdomain); FINISH_CHECK(str_temp != NULL, "getport failed"); if (strlen(str_temp) > 0) { DEBUG("VALID SUBDOMAIN DETECTED >%s|%s<", str_global_developers, str_temp); int_global_current_conn_port = atoi(str_temp); bol_valid_subdomain = true; } SFREE(str_temp); } else { FINISH_CAT_CSTR(str_current_subdomain, ""); } DEBUG(">%s|%s|%i|%i<", str_uri, "/auth_envelope/accept_auth", strlen(str_uri), strncmp(str_uri, "/auth_envelope/accept_auth", 26) == 0); DEBUG("test0>str_request: %s", str_request); str_cookie_envelope = str_cookie(str_request, "envelope"); DEBUG("test1"); bol_global_public = false; DEBUG("str_uri: >%s< str_uri + 13 + strcspn(str_uri + 13, \"./\"): >%s<", str_uri, str_uri + 13 + strcspn(str_uri + 13, "./")); // if the URL does not start with /v1 // then serve from the web_root if (strncmp(str_uri, "/v1/", 4) != 0) { str_response = link_web_root(csock, str_uri, bol_valid_subdomain ? str_current_subdomain : ""); FINISH_CHECK(str_response != NULL, "link_web_root failed"); goto finish; // postgres functions that start with actionnc_ or acceptnc_ // these CAN have a COOKIE, but it WON'T BE USED // set up a public connection } else if (//str_cookie_envelope == NULL && strlen(str_uri) >= 13 && strncmp(str_uri, "/v1/cluster/", 12) == 0 && (strncmp(str_uri + 13 + strcspn(str_uri + 13, "./"), ".acceptnc_", 10) == 0 || strncmp(str_uri + 13 + strcspn(str_uri + 13, "./"), ".actionnc_", 10) == 0)) { cnxn = set_cnxn_public(csock, str_request); // built in envelope functions // these links CAN have a COOKIE, but if we don't then set up a public connection } else if (str_cookie_envelope == NULL && ((strlen(str_uri) >= 18 && strncmp(str_uri, "/v1/env/action_info" , 18) == 0) || (strlen(str_uri) >= 20 && strncmp(str_uri, "/v1/env/action_upload" , 20) == 0) || (strlen(str_uri) >= 22 && strncmp(str_uri, "/v1/env/accept_download" , 22) == 0) || (strlen(str_uri) >= 23 && strncmp(str_uri, "/v1/envelope/action_info" , 23) == 0) || (strlen(str_uri) >= 25 && strncmp(str_uri, "/v1/envelope/action_upload" , 25) == 0) || (strlen(str_uri) >= 27 && strncmp(str_uri, "/v1/envelope/accept_download", 27) == 0) || (strlen(str_uri) >= 21 && strncmp(str_uri, "/v1/env/action_select", 21) == 0) || (strlen(str_uri) >= 21 && strncmp(str_uri, "/v1/env/action_update", 21) == 0) || (strlen(str_uri) >= 21 && strncmp(str_uri, "/v1/env/action_insert", 21) == 0) || (strlen(str_uri) >= 21 && strncmp(str_uri, "/v1/env/action_delete", 21) == 0) || (strlen(str_uri) >= 20 && strncmp(str_uri, "/v1/env/action_order" , 20) == 0))) { cnxn = set_cnxn_public(csock, str_request); // authentication links for normal user, these CAN have a COOKIE } else if ((strlen(str_uri) >= 26 && strncmp(str_uri, "/auth_envelope/accept_auth", 26) == 0) || (strlen(str_uri) >= 12 && strncmp(str_uri, "/v1/env/auth", 12) == 0)) { /* FINISH_CHECK(strncmp(str_current_subdomain, str_global_subdomain, strlen(str_global_subdomain)) == 0, "Must be in \"%s\" subdomain.", str_global_subdomain); */ str_response = link_auth(cnxn, str_request); FINISH_CHECK(str_response != NULL, "link_auth failed"); goto finish; // authentication links for superuser, these REQUIRE a COOKIE } else if ((strlen(str_uri) >= 16 && strncmp(str_uri, "/v1/postage/auth", 16) == 0)) { str_response = link_auth_postage(str_request); FINISH_CHECK(str_response != NULL, "link_auth_postage failed"); goto finish; // superuser links, these REQUIRE a COOKIE } else if (strncmp(str_uri, "/v1/dev" , 7 ) == 0 || strncmp(str_uri, "/v1/postage", 11) == 0 || strncmp(str_uri, "/v1/sql" , 7 ) == 0) { cnxn = set_cnxn_postage(csock, str_uri, str_request); // subdomain links, these REQUIRE a COOKIE } else if (bol_valid_subdomain) { cnxn = set_cnxn_test(csock, str_uri, str_request); // production links, these REQUIRE a COOKIE } else { cnxn = set_cnxn(csock, str_uri, str_request); } //IF NULL THEN EXIT, CSOCK IS ALREADY WRITTEN TO BY set_cnxn AND set_cnxn_test if (cnxn == NULL) { //if we use FINISH_CHECK, there will be a sunlogf //we don't want a sunlogf cause there is no error. we just want to return goto finish; } // cnxn GARANTEED TO BE VALID HERE //if public cookie (or nocookie always) then public action if (bol_global_public) { str_response = main_public_action(cnxn, csock, str_uri, str_request, int_request_len, bol_valid_subdomain ? str_current_subdomain : ""); FINISH_CHECK(str_response != NULL, "link_auth failed"); goto finish; } //################################################################################################ //########################## HAVE COOKIE, HAVE CNXN, PARSE REQUESTS ############################## DEBUG("COOKIE IS VALID"); //not a webroot request if (strncmp(str_uri, "/v1/", 4) == 0) { char *ptr_uri = str_uri + 3; //this link is for accessing the database if (strlen(ptr_uri) >= 9 && strncmp(ptr_uri, "/cluster/", 9) == 0) { str_response = link_cluster(cnxn, ptr_uri, str_request, csock); FINISH_CHECK(str_response != NULL, "link_cluster failed"); //this link is for uploading a file to role } else if (strlen(ptr_uri) >= 16 && strncmp(ptr_uri, "/upload_envelope", 16) == 0) { str_response = link_upload(cnxn, str_request, int_request_len, bol_valid_subdomain ? str_current_subdomain : ""); FINISH_CHECK(str_response != NULL, "link_upload failed"); //this link is for builtin c actions like action_select (read from view) } else if (strlen(ptr_uri) >= 10 && strncmp(ptr_uri, "/envelope/", 10) == 0) { // link system is in envelope_handle_c.c str_response = link_system(cnxn, csock, ptr_uri + 5, str_request, int_request_len, bol_valid_subdomain ? str_current_subdomain : ""); FINISH_CHECK(str_response != NULL, "link_system failed"); //shorter version of the above link } else if (strlen(ptr_uri) >= 5 && strncmp(ptr_uri, "/env/", 5) == 0) { // link system is in envelope_handle_c.c str_response = link_system(cnxn, csock, ptr_uri, str_request, int_request_len, bol_valid_subdomain ? str_current_subdomain : ""); FINISH_CHECK(str_response != NULL, "link_system failed"); //read file from role } else if (strlen(ptr_uri) >= 6 && strncmp(ptr_uri, "/role/", 6) == 0) { str_response = link_role(csock, cnxn, ptr_uri, bol_valid_subdomain ? str_current_subdomain : ""); FINISH_CHECK(str_response != NULL, "link_role failed"); //read app file } else if (strncmp(ptr_uri, "/app/", 5) == 0) { str_response = link_apps(csock, cnxn, ptr_uri, bol_valid_subdomain ? str_current_subdomain : ""); FINISH_CHECK(str_response != NULL, "link_apps failed"); //read app file, but require superuser } else if (strncmp(ptr_uri, "/dev/", 5) == 0) { str_response = link_apps(csock, cnxn, ptr_uri, bol_valid_subdomain ? str_current_subdomain : ""); FINISH_CHECK(str_response != NULL, "link_apps failed"); //more builtin c actions, but require superuser } else if (strlen(ptr_uri) >= 9 && strncmp(ptr_uri, "/postage/", 9) == 0) { // link system is in postage_handle_c2.c str_response = link_system_postage(cnxn, csock, ptr_uri, str_request, int_request_len); FINISH_CHECK(str_response != NULL, "link_system_postage failed"); //run arbitrary sql, must be superuser } else if (strlen(ptr_uri) >= 4 && strncmp(ptr_uri, "/sql", 4) == 0) { str_response = link_sql(csock, cnxn, str_request); FINISH_CHECK(str_response != NULL, "link_sql failed"); //if none of these, error } else { NOTICE("REQUEST TYPE: UNHANDLED str_uri:%s", str_uri); FINISH_CAT_CSTR(str_response, "HTTP/1.1 303 See Other\r\nLocation: /index.html\r\n"); } //web_root request should already have been handled, error } else { NOTICE("REQUEST TYPE: UNHANDLED str_uri:%s", str_uri); FINISH_CAT_CSTR(str_response, "HTTP/1.1 303 See Other\r\nLocation: /index.html\r\n"); } finish: if (str_response != NULL) { INFO("REPLACE COOKIE IN str_response"); //replace cookie before expiration str_complete_response = replace_cookie(str_response, str_request); SFREE_PWORD(str_response); DEBUG("str_complete_response: %s", str_complete_response); if ((long)write(csock, str_complete_response, strlen(str_complete_response)) != (long)strlen(str_complete_response)) { str_complete_response = ERROR_RESPONSE("write failed: %d (%s)", errno, strerror(errno)); write(csock, str_complete_response, strlen(str_complete_response)); } } else { ERROR_NORESPONSE("no str_response"); } fsync(csock); NOTICE("RESPONSE SENT %d bytes", strlen(str_complete_response)); if (cnxn != NULL) PQfinish(cnxn); SFREE_PWORD(str_request); SFREE_ALL(); return true; }