static void* MainChatbotServer() { sprintf(serverLogfileName,"LOGS/serverlog%d.txt",port); ServerStartup(); // get initial control over the mutex so we can start. - on linux if thread dies, we must reacquire here // we now own the chatlock clock_t lastTime = ElapsedMilliseconds(); if (setjmp(scriptJump[MAIN_RECOVERY])) // crashes come back to here { printf("***Server exception\r\n"); ReportBug("***Server exception\r\n"); #ifdef WIN32 char* bad = GetUserVariable("$crashmsg"); if (*bad) strcpy(outputFeed,bad); else strcpy(outputFeed,"Hey, sorry. I forgot what I was thinking about."); ServerTransferDataToClient(""); #endif ResetBuffers(); // in the event of a trapped bug, return here, we will still own the chatlock } chatbotExists = true; // if a client can get the chatlock now, he will be happy Log(SERVERLOG,"Server ready\r\n"); printf("Server ready: %s\r\n",serverLogfileName); #ifdef WIN32 _try { // catch crashes in windows #endif int counter = 0; while (1) { ServerGetChatLock(); startServerTime = ElapsedMilliseconds(); // chatlock mutex controls whether server is processing data or client can hand server data. // That we now have it means a client has data for us. // we own the chatLock again from here on so no new client can try to pass in data. // CLIENT has passed server in globals: clientBuffer (ip,user,bot,message) // We will send back his answer in clientBuffer, overwriting it. char user[MAX_WORD_SIZE]; char bot[MAX_WORD_SIZE]; char* ip = clientBuffer; char* ptr = ip; // incoming is 4 strings together: ip, username, botname, message ptr += strlen(ip) + 1; // ptr to username strcpy(user,ptr); // allow user var to be overwriteable, hence a copy ptr += strlen(ptr) + 1; // ptr to botname strcpy(bot,ptr); ptr += strlen(ptr) + 1; // ptr to message strcpy(inputFeed,ptr); // xfer user message to our incoming feed echo = false; PerformChat(user,bot,inputFeed,ip,outputFeed); // this takes however long it takes, exclusive control of chatbot. #ifdef STATSERVER clock_t now = ElapsedMilliseconds(); if ( (now / 1000) > (lastTime / 1000)) // starting different second { printf("%d\r\n",counter); counter = 0; lastTime = now; } ++counter; if ((now-startServerTime) > 2000) { printf("Compute Stall? %d\r\n",now-startServerTime); } #endif ServerTransferDataToClient(priorMessage); } #ifdef WIN32 }_except (true) { ReportBug("crash\r\n"); Crash();} #endif return NULL; }
VOID CALLBACK TimeCheck( HWND hwnd, UINT uMsg,UINT_PTR idEvent,DWORD dwTime) // every 100 ms { char c; static bool init = false; static int inputCount = 0; if (!init) { init = true; // char word[MAX_WORD_SIZE]; // GetCurrentDir(word, MAX_WORD_SIZE); InitChatbot(computerName); RECT rect; GetClientRect(hwnd, &rect); InvalidateRect(hwnd, &rect, TRUE); strcpy(response,"Chatbot initialization complete"); } static int counter = 0; ++counter; // increament each timer interrupt, tracking how long since last key input from user static char lastchar = 0; static bool keyhit = false; while ((c = ReadChar())) // returns 0 if nothing found { keyhit = true; // user input seen since last output RECT rect; GetClientRect(hwnd, &rect); InvalidateRect(hwnd, &rect, TRUE); if ( c == 8) // backspace { if ( msgPtr != inputMessage) *--msgPtr = 0; } else if ( c == '\n' || c == '\r') // prepare for NEW input and get response { if (msgPtr == inputMessage) continue; // ignore empty lines *msgPtr = 0; counter = 100; // treat as end of input break; // dont read until we have responded } else if (msgPtr == inputMessage && (c == ' ' || c == '\t' )) continue; // ignore leading whitespace. else // accept new character { *msgPtr++ = c; lastchar = c; *msgPtr = 0; } counter = 0; // start time wait over again } // do we have something we want to respond to? bool trigger = false; if (counter >= 30 && *inputMessage && (lastchar == '.' || lastchar == '?' || lastchar == '!')) trigger = true; // 3 sec passed and have input ended on closer else if (counter >= 70 && *inputMessage) trigger = true; // 7 seconds + have lingering input // or timer oob goes off char oob[MAX_WORD_SIZE]; *oob = 0; ProcessInputDelays(oob,keyhit); if (trigger || *oob) { if (*oob) strcpy(ourMainInputBuffer,oob); // priority is to alarm callback. others will be only if no user input anyway else { strcpy(ourMainInputBuffer,inputMessage); // clear all signs of user input lastchar = 0; *inputMessage = 0; msgPtr = inputMessage; keyhit = false; } PerformChat(loginID,computerID,ourMainInputBuffer,NULL,ourMainOutputBuffer); strcpy(response,ourMainOutputBuffer); callBackDelay = 0; // now turned off after an output ProcessOOB(ourMainOutputBuffer); // process relevant out of band messaging and remove char word[MAX_WORD_SIZE]; char* p = SkipWhitespace(ourMainOutputBuffer); ReadCompiledWord(p,word); if (!*word) strcpy(p,"huh?"); // in case we fail to generate output // transmit message to user ++inputCount; while (*p) { if (SendChar(*p,p[1],inputCount)) p++; // got sent } SendChar('\n',0,inputCount); if (loopBackDelay) loopBackTime = ElapsedMilliseconds() + loopBackDelay; // resets every output // write out last sequence id FILE* out = fopen("sequence", "wb"); fprintf(out,"%d",sequence); fclose(out); counter = 0; RECT rect; GetClientRect(hwnd, &rect); InvalidateRect(hwnd, &rect, TRUE); } }