📄 http.c
字号:
tmp[i] = 0; toLower(tmp); head = allocBuff(info, sizeof (struct httpHeader)); head->next = NULL; head->name = tmp; head->value = line; if (info->lastHead == NULL) info->firstHead = head; else info->lastHead->next = head; info->lastHead = head; debug(DEBUG_REQUEST, "new header, name = %s, value = '%s'\n", info->lastHead->name, info->lastHead->value); } return 0; case STATE_RESPONSE: debug(DEBUG_CONNECTION, "connection state is STATE_RESPONSE\n"); unescape(info->path); len = strlen(confPubDir); pub = (len > 0 && strncmp(info->path, confPubDir, len) == 0 && (info->path[len] == 0 || info->path[len] == '/')); debug(DEBUG_REQUEST, "%s path\n", (pub == 0) ? "protected" : "public"); if (pub == 0 && (confUser != NULL || confPassword != NULL)) { debug(DEBUG_REQUEST, "authentication required\n"); for (head = info->firstHead; head != NULL; head = head->next) if (memcmp(head->name, "authorization", 14) == 0) break; if (head == NULL) { debug(DEBUG_REQUEST, "no authorization header present\n"); writeError(info, 401); return 0; } tmp = getToken(&head->value); if (tmp == NULL || strcmp(tmp, "Basic") != 0) { error("\"Basic\" authorization info expected\n"); writeError(info, 401); return 0; } tmp = getToken(&head->value); if (tmp == NULL) { error("authorization info lacks base-64 encoded data\n"); writeError(info, 401); return 0; } tmp2 = allocBuff(info, strlen(tmp) * 3 / 4 + 1); if (decBase64((unsigned char *)tmp2, tmp) < 0) { error("base-64 decode failed\n"); writeError(info, 401); return 0; } for (i = 0; tmp2[i] != ':' && tmp2[i] != 0; i++); if (tmp2[i] == 0) { error("authorization info lacks ':'\n"); writeError(info, 401); return 0; } tmp2[i++] = 0; debug(DEBUG_REQUEST, "user = %s, password = %s\n", tmp2, tmp2 + i); if ((confUser != NULL && strcmp(confUser, tmp2) != 0) || (confPassword != NULL && strcmp(confPassword, tmp2 + i) != 0)) { error("user authentication failed\n"); writeError(info, 401); return 0; } } if (isDirectory(confRootDir, info->path) > 0) { debug(DEBUG_REQUEST, "path is a directory\n"); tmp = fullPath(info->path, confIndexFile); debug(DEBUG_REQUEST, "updated path = %s\n", tmp); info->path = allocBuff(info, strlen(tmp) + 1); strcpy(info->path, tmp); freeMem(tmp); } if (openFile(&info->fileId, confRootDir, info->path) < 0) { error("cannot find resource %s in root directory %s\n", info->path, confRootDir); writeError(info, 404); return 0; } for (i = 0; extMap[i].ext != NULL; i++) { len = strlen(extMap[i].ext); len2 = strlen(info->path); if (len2 >= len && memcmp(info->path + len2 - len, extMap[i].ext, len) == 0) break; } if (extMap[i].ext != NULL) { info->state = extMap[i].state; info->contType = extMap[i].type; debug(DEBUG_REQUEST, "extension recognized, next state = %d, content type = %s\n", info->state, info->contType); } else info->state = STATE_FILE; if (strcmp(info->verb, "HEAD") == 0) { closeFile(&info->fileId); writeHeaders(info, 200); info->state = STATE_DRAIN; } return 0; case STATE_FILE: debug(DEBUG_CONNECTION, "connection state is STATE_FILE\n"); for (;;) { len = readFileOs(&info->fileId, fileBuff, sizeof (fileBuff)); debug(DEBUG_CONNECTION, "read %d bytes from file\n", len); if (len <= 0) { if (len < 0) { closeFile(&info->fileId); info->contLen = info->write[2].cont; writeHeaders(info, 200); info->state = STATE_DRAIN; } break; } writeBuff(&info->write[2], fileBuff, len); } return 0; case STATE_LSP: debug(DEBUG_CONNECTION, "connection state is STATE_LSP\n"); tmp = allocBuff(info, strlen(info->path) + 4 + 1); setExtension(tmp, info->path, ".lua"); debug(DEBUG_LUA, "lua file name = %s\n", tmp); if (lspToLua(confRootDir, info->path, confWorkDir, tmp) < 0) { error("cannot transform %s into %s\n", info->path, tmp); writeError(info, 500); return 0; } tmp2 = allocBuff(info, strlen(info->path) + 4 + 1); setExtension(tmp2, info->path, ".lex"); debug(DEBUG_LUA, "lex file name = %s\n", tmp2); if (luaToLex(&errMsg, confWorkDir, tmp, tmp2) < 0) { error("cannot transform %s into %s\n", tmp, tmp2); writeErrorMsg(info, 500, errMsg); if (errMsg != NULL) freeMem(errMsg); return 0; } tmp = info->para; if (tmp != NULL) { len = 3 * sizeof (char *); for (i = 0; tmp[i] != 0; i++) { if (tmp[i] == '+') tmp[i] = ' '; if (tmp[i] == '=' || tmp[i] == '&') len += sizeof (char *); } argList = allocBuff(info, len); i = 0; k = 0; while (tmp[i] != 0) { argList[k++] = tmp + i; while (tmp[i] != 0 && tmp[i] != '=') i++; if (tmp[i] == 0) { error("end of parameters while looking for '='\n"); writeError(info, 400); return 0; } tmp[i++] = 0; debug(DEBUG_LUA, "parameter name = '%s'\n", argList[k - 1]); argList[k++] = tmp + i; while (tmp[i] != 0 && tmp[i] != '&') i++; if (tmp[i] != 0) tmp[i++] = 0; debug(DEBUG_LUA, "parameter value = '%s'\n", argList[k - 1]); } for (i = 0; i < k; i++) unescape(argList[i]); argList[k++] = NULL; argList[k++] = NULL; } else argList = NULL; currSess = NULL; for (head = info->firstHead; head != NULL; head = head->next) if (memcmp(head->name, "cookie", 7) == 0 && cookieToSession(&sessId, head->value) >= 0) break; if (head != NULL) { debug(DEBUG_SESSION, "looking for existing session\n"); for (i = 0; i < numSess && sess[i]->id != sessId; i++); if (i < numSess) { debug(DEBUG_SESSION, "existing session found\n"); currSess = sess[i]; os_now(&currSess->time); } } if (currSess == NULL) { debug(DEBUG_SESSION, "no existing session\n"); info->newSess = newSessInfo(); currSess = info->newSess; } if (runLua(&errMsg, info, confWorkDir, tmp2, argList, &currSess->data) < 0) { error("cannot run %s\n", tmp2); if (info->newSess != NULL) { debug(DEBUG_SESSION, "cleaning up newly created session\n"); if (info->newSess->data != NULL) { debug(DEBUG_SESSION, "freeing lua context\n"); freeLuaSession(info->newSess->data); } freeMem(info->newSess); info->newSess = NULL; } debug(DEBUG_SESSION, "purging io buffer\n"); freeInOutBuff(&info->write[1]); freeInOutBuff(&info->write[2]); initInOutBuff(&info->write[1]); initInOutBuff(&info->write[2]); writeErrorMsg(info, 500, errMsg); if (errMsg != NULL) freeMem(errMsg); return 0; } debug(DEBUG_SESSION, "lua code successfully executed\n"); if (info->newSess != NULL) { if (info->newSess->data == NULL) { debug(DEBUG_SESSION, "no session required\n"); freeMem(info->newSess); info->newSess = NULL; } else { if (numSess == MAX_SESS) { error("session limit reached, deleting least recently used session %d\n", sess[0]->id); freeLuaSession(sess[0]->data); freeMem(sess[0]); for (i = 0; i < MAX_SESS - 1; i++) sess[i] = sess[i + 1]; numSess--; } sess[numSess++] = info->newSess; debug(DEBUG_SESSION, "session added\n"); } } else { debug(DEBUG_SESSION, "aging sessions\n"); for (i = 0; sess[i]->id != currSess->id; i++); while (i < numSess - 1) { sess[i] = sess[i + 1]; i++; } if (currSess->data == NULL) { debug(DEBUG_SESSION, "session not required any longer\n"); sess[i] = NULL; freeMem(currSess); numSess--; } else { debug(DEBUG_SESSION, "session stored\n"); sess[i] = currSess; } } info->contLen = info->write[2].cont; writeHeaders(info, 200); info->state = STATE_DRAIN; return 0; case STATE_DRAIN: debug(DEBUG_CONNECTION, "connection state is STATE_DRAIN\n"); debug(DEBUG_CONNECTION, "which = %d\n", info->which); if (info->write[info->which].first == NULL) info->which++; if (info->which == 3) return -1; return 0; } return 0;}int httpService(int freq){ struct fileId *sockId; struct ipAddr *addr; int i, k;#ifdef TAS_BLOCK struct fileId *waitIds[MAX_CONN]; int *waitFlags[MAX_CONN];#endif unsigned int micro, microLimit; struct tasMessage *tasMsg; micro = getMicro();#ifdef TAS_BLOCK for (i = 0; i < numConn; i++) { waitIds[i] = conn[i]->sockId; waitFlags[i] = &conn[i]->flags; conn[i]->flags = FLAG_READ; if (conn[i]->firstWrite != NULL) conn[i]->flags |= FLAG_WRITE; } if (waitForSockets(waitIds, waitFlags, numConn) < 0) return 0;#endif while (numConn < MAX_CONN) { if (acceptConn(&sockId, &addr) < 0) break; conn[numConn++] = newConnInfo(sockId, addr); } i = 0; while (i < numConn) { if (((conn[i]->flags & FLAG_READ) != 0 && readConn(conn[i]) < 0) || ((conn[i]->flags & FLAG_WRITE) != 0 && writeConn(conn[i]) < 0) || serviceConn(conn[i]) < 0) { closeFile(conn[i]->sockId); freeConnInfo(conn[i]); for (k = i; k < numConn - 1; k++) conn[k] = conn[k + 1]; conn[k] = NULL; numConn--; } else i++; } while (numSess > 0 && confSessTime > 0 && timedOut(&sess[0]->time, confSessTime) >= 0) { error("session %d timed out\n", sess[0]->id); freeLuaSession(sess[0]->data); freeMem(sess[0]); for (i = 0; i < numSess - 1; i++) sess[i] = sess[i + 1]; numSess--; debug(DEBUG_SESSION, "%d sessions left\n", numSess); } while (numTasMsg > 0 && confMessTime > 0 && timedOut(&firstTasMsg->time, confMessTime) >= 0) { tasMsg = firstTasMsg; debug(DEBUG_MESSAGE, "message timed out, service ='%s', string = '%s', from = %s\n", tasMsg->service, tasMsg->string, tasMsg->from); firstTasMsg = firstTasMsg->next; if (lastTasMsg == tasMsg) lastTasMsg = NULL; freeMem(tasMsg->service); freeMem(tasMsg->string); freeMem(tasMsg->from); freeMem(tasMsg); numTasMsg--; debug(DEBUG_MESSAGE, "%d messages left\n", numTasMsg); } micro = getMicro() - micro; microLimit = (10000 * confQuantum) / freq; debug(DEBUG_QUANTUM, "service time = %u us, limit = %u us\n", micro, microLimit); if (microLimit > 0 && micro > microLimit) error("service took longer than expected (%u us, limit is %u us)\n", micro, microLimit); return 0;}void httpShutdown(void){ closeMainSocket();}void httpAddTasMessage(const char *service, const char *string, const char *from){ struct tasMessage *msg; debug(DEBUG_MESSAGE, "adding message, service = %s, string = %s, from = %s\n", service, string, from); msg = allocMem(sizeof (struct tasMessage)); msg->next = NULL; os_now(&msg->time); msg->service = myStrdup(service); msg->string = myStrdup(string); msg->from = myStrdup(from); if (lastTasMsg != NULL) lastTasMsg->next = msg; else firstTasMsg = msg; lastTasMsg = msg; numTasMsg++; debug(DEBUG_MESSAGE, "new number of messages: %d\n", numTasMsg); debug(DEBUG_MESSAGE, "limiting message queue length\n"); while (confMessLimit > 0 && numTasMsg > confMessLimit) { msg = firstTasMsg; debug(DEBUG_MESSAGE, "message removed, service ='%s', string = '%s', from = %s\n", msg->service, msg->string, msg->from); firstTasMsg = firstTasMsg->next; if (lastTasMsg == msg) lastTasMsg = NULL; freeMem(msg->service); freeMem(msg->string); freeMem(msg->from); freeMem(msg); numTasMsg--; } debug(DEBUG_MESSAGE, "%d messages left\n", numTasMsg);}int httpGetTasMessage(const char *service, char **string, char **from){ struct tasMessage *msg, *prevMsg; debug(DEBUG_MESSAGE, "getting message, service = %s\n", service); prevMsg = NULL; debug(DEBUG_MESSAGE, "walking through message queue\n"); for (msg = firstTasMsg; msg != NULL; msg = msg->next) { debug(DEBUG_MESSAGE, " service = %s, string = %s\n", msg->service, msg->string); if (strcmp(msg->service, service) == 0) break; prevMsg = msg; } debug(DEBUG_MESSAGE, "walk finished\n"); if (msg == NULL) { debug(DEBUG_MESSAGE, "no message found\n"); return -1; } if (msg == firstTasMsg) firstTasMsg = msg->next; else prevMsg->next = msg->next; if (msg == lastTasMsg) lastTasMsg = prevMsg; *string = msg->string; *from = msg->from; freeMem(msg->service); freeMem(msg); numTasMsg--; debug(DEBUG_MESSAGE, "%d messages left\n", numTasMsg); debug(DEBUG_MESSAGE, "returning '%s' received from %s\n", *string, *from); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -