// find an entry in the db; return offset of id or FAIL int findKey(char *id) { int start = STARTDB; while (start < ENDDB-4) { // find the next entry start = findoccupied(start); if (start == FAIL) return FAIL; // start points to EEPROM id - check for match with id if (eestrmatch(start, id)) return start; // no match - skip the id and its value and continue scanning start = findend(start); // scan past id start = findend(start); // and value } return FAIL; }
// list the strings in the avpdb void cmd_ls(void) { int start = STARTDB; for (;;) { // find the next entry start = findoccupied(start); if (start == FAIL) return; eeputs(start); msgp(M_defmacro); start = findend(start); eeputs(start); spb('"'); speol(); start = findend(start); } }
void prompt(void) { char buf[IDLEN+1]; // Run the script named "prompt" if there is one else print "> " strncpy_P(buf, getmsg(M_promptid), IDLEN); // get the name "prompt" in our cmd buf int entry = findKey(buf); if (entry >= 0) doCommand(kludge(findend(entry))); else msgp(M_prompt); // else print default prompt }
// list the strings in the avpdb void cmd_ls(void) { int start = STARTDB; for (;;) { // find the next entry start = findoccupied(start); if (start == FAIL) return; msgp(M_function); spb(' '); eeputs(start); spb(' '); spb('{'); start = findend(start); eeputs(start); spb('}'); spb(';'); speol(); start = findend(start); } }
void doMacroCall(int macroaddress) { char op = sym; // save sym for restore if (macroaddress >= 0) { char *fetchmark = fetchptr; // save the current parse pointer // call the macro calleeprommacro(findend(macroaddress)); // register the macro into the parser stream getsym(); getstatementlist(); // parse and execute the macro code here if (sym != s_eof) expected(M_eof); // restore parsing context so we can resume cleanly fetchptr = fetchmark; // restore pointer primec(); // and inchar sym = op; // restore saved sym } }
// call a macro and push its return value on the stack // void domacrocall(int macroaddress) { if (macroaddress >= 0) { parsearglist(); byte thesym = sym; // save sym for restore vpush(symval); // and symval char *fetchmark = fetchptr; // save the current parse pointer // call the macro calleeprommacro(findend(macroaddress)); // register the macro into the parser stream getsym(); // fetch its first symbol numvar ret = getstatementlist(); // parse and execute the macro code here // if (sym != s_eof) expected(M_eof); // restore parsing context so we can resume cleanly symval = vpop(); // restore symval sym = thesym; // restore saved sym releaseargblock(); // drop the args fetchptr = fetchmark; // restore pointer primec(); // and inchar vpush(ret); // send back our return value } }
////////// // // runBackgroundTasks // // Runs one eligible background task per invocation // Returns true if a task was run // void runBackgroundTasks(void) { byte i; #ifdef suspendBackground if (suspendBackground) return; #endif for (i=0; i<NUMTASKS; i++) { // run one task per call on a round robin basis if (++curtask >= NUMTASKS) curtask = 0; if ((tasklist[curtask] != SLOT_FREE) && (((signed long) millis() - (signed long) waketime[curtask])) >= 0) { // run it with the background flag set background = 1; execscript(SCRIPT_EEPROM, findend(tasklist[curtask]), 0); // schedule the next time quantum for this task waketime[curtask] = millis() + snoozetime[curtask]; background = 0; break; } } }
// Get a statement void getstatement(void) { #if !defined(TINY85) chkbreak(); #endif if (sym == s_while) { // at this point sym is pointing at s_while, before the conditional expression // save fetchptr so we can restart parsing from here as the while iterates char *fetchmark = fetchptr; for (;;) { fetchptr = fetchmark; // restore to mark primec(); // set up for mr. getsym() getsym(); // fetch the start of the conditional if (!getnum()) { //longjmp(env, X_EXIT); // get the conditional; exit on false sym = s_eof; // we're finished here. move along. return; } if (sym != s_colon) expectedchar(':'); getsym(); // eat : getstatementlist(); } } else if (sym == s_if) { getsym(); // fetch the start of the conditional if (!getnum()) { //longjmp(env, X_EXIT); // get the conditional; exit on false sym = s_eof; return; } if (sym != s_colon) expectedchar(':'); getsym(); // eat : getstatementlist(); } #if SKETCH // The switch statement: call one of N macros based on a selector value // switch <numval>: macroid1, macroid2,.., macroidN // numval < 0: numval = 0 // numval > N: numval = N else if (sym == s_switch) { getsym(); // eat "switch" numvar selector = getnum(); // evaluate the switch value if (selector < 0) selector = 0; if (sym != s_colon) expectedchar(':'); // we sit before the first macroid // scan and discard the <selector>'s worth of macro ids // that sit before the one we want for (;;) { getsym(); // get an id, sets symval to its eeprom addr as a side effect if (sym != s_macro) expected (6); // TODO: define M_macro instead of 6 getsym(); // eat id, get separator; assume symval is untouched if ((sym == s_semi) || (sym == s_eof)) break; // last case is default so we exit always if (sym != s_comma) expectedchar(','); if (!selector) break; // ok, this is the one we want to execute selector--; // one down... } // call the macro whose addr is squirreled in symval all this time // on return, the parser is ready to pick up where we left off doMacroCall(symval); // scan past the rest of the unused switch options, if any // TODO: syntax checking for non-chosen options could be made much tighter at the cost of some space while ((sym != s_semi) && (sym != s_eof)) getsym(); // scan to end of statement without executing } #endif else if ((sym == s_macro) || (sym == s_undef)) { // macro def or ref getsym(); // scan past macro name to next symbol: ; or := if (sym == s_define) { // macro definition: macroid := strvalue // to define the macro, we need to copy the id somewhere on the stack // to avoid having this local buffer in every getstatement stack frame, // we break out defineMacro here to a separate function that only eats that // stack in the case that a macro is being defined #ifdef TINY85 unexpected(M_defmacro); #else defineMacro(); #endif } else if ((sym == s_semi) || (sym == s_eof)) { // valid macro reference: let's call it #if SKETCH doMacroCall(symval); // parseid stashes the macro address in symval #else char op = sym; // save sym for restore expval = findKey(idbuf); // assumes id in idbuf isn't clobbered since getsym() above if (expval >= 0) { char *fetchmark = fetchptr; // save the current parse pointer // call the macro calleeprommacro(findend(expval)); // register the macro into the parser stream getsym(); getstatementlist(); // parse and execute the macro code here if (sym != s_eof) expected(M_eof); // restore parsing context so we can resume cleanly fetchptr = fetchmark; // restore pointer primec(); // and inchar sym = op; // restore saved sym: s_semi or s_eof } else unexpected(M_id); #endif } else expectedchar(';'); //else getexpression(); // assume it was macro1+32+macro2... } else if (sym == s_run) { // run macroname getsym(); if (sym != s_macro) unexpected(M_id); #if 0 // address of macroid is in symval via parseid startTask(kludge(symval)); getsym(); #else // address of macroid is in symval via parseid // check for [,snoozeintervalms] getsym(); // eat macroid to check for comma; symval untouched if (sym == s_comma) { vpush(symval); getsym(); // eat the comma getnum(); // get a number or else startTask(kludge(vpop()), expval); } else startTask(kludge(symval), 0); #endif } else if (sym == s_stop) { getsym(); if (sym == s_mul) { // stop * stops all tasks initTaskList(); getsym(); } else if ((sym == s_semi) || (sym == s_eof)) { if (background) stopTask(curtask); // stop with no args stops the current task IF we're in back else initTaskList(); // in foreground, stop all } else stopTask(getnum()); } else if (sym == s_boot) reboot(); #if !defined(TINY85) else if (sym == s_rm) { // rm "sym" or rm * getsym(); if (sym == s_macro) { eraseentry(idbuf); } else if (sym == s_mul) nukeeeprom(); else expected(M_id); getsym(); } else if (sym == s_ps) showTaskList(); else if (sym == s_peep) { getsym(); cmd_peep(); } else if (sym == s_ls) { getsym(); cmd_ls(); } else if (sym == s_help) { getsym(); cmd_help(); } else if (sym == s_print) { getsym(); cmd_print(); } #endif #ifdef HEX_UPLOAD // a line beginning with a colon is treated as a hex record // containing data to upload to eeprom // // TODO: verify checksum // else if (sym == s_colon) { // fetchptr points at the byte count byte byteCount = gethex(2); // 2 bytes byte count int addr = gethex(4); // 4 bytes address byte recordType = gethex(2); // 2 bytes record type; now fetchptr -> data if (recordType == 1) reboot(); // reboot on EOF record (01) if (recordType != 0) return; // we only handle the data record (00) if (addr == 0) nukeeeprom(); // auto-clear eeprom on write to 0000 while (byteCount--) eewrite(addr++, gethex(2)); // update the eeprom gethex(2); // discard the checksum getsym(); // and re-prime the parser } #endif else { getexpression(); } }
// // Recursive descent parser, old-school style. // void getfactor(void) { numvar thesymval = symval; byte thesym = sym; getsym(); // eat the sym we just saved switch (thesym) { case s_nval: vpush(thesymval); break; case s_nvar: if (sym == s_equals) { // assignment, push is after the break; getsym(); assignVar(thesymval, getnum()); } else if (sym == s_incr) { // postincrement nvar++ vpush(getVar(thesymval)); assignVar(thesymval, getVar(thesymval) + 1); getsym(); break; } else if (sym == s_decr) { // postdecrement nvar-- vpush(getVar(thesymval)); assignVar(thesymval, getVar(thesymval) - 1); getsym(); break; } vpush(getVar(thesymval)); // both assignment and reference get pushed here break; case s_nfunct: dofunctioncall(thesymval); // get its value onto the stack break; // Script-function-returning-value used as a factor case s_script_eeprom: // macro returning value callscriptfunction(SCRIPT_EEPROM, findend(thesymval)); break; case s_script_progmem: callscriptfunction(SCRIPT_PROGMEM, thesymval); break; case s_script_file: callscriptfunction(SCRIPT_FILE, (numvar) 0); // name implicitly in idbuf! break; case s_apin: // analog pin reference like a0 if (sym == s_equals) { // digitalWrite or analogWrite getsym(); analogWrite(thesymval, getnum()); vpush(expval); } else vpush(analogRead(thesymval)); break; case s_dpin: // digital pin reference like d1 if (sym == s_equals) { // digitalWrite or analogWrite getsym(); digitalWrite(thesymval, getnum()); vpush(expval); } else vpush(digitalRead(thesymval)); break; case s_incr: if (sym != s_nvar) expected(M_var); assignVar(symval, getVar(symval) + 1); vpush(getVar(symval)); getsym(); break; case s_decr: // pre decrement if (sym != s_nvar) expected(M_var); assignVar(symval, getVar(symval) - 1); vpush(getVar(symval)); getsym(); break; case s_arg: // arg(n) - argument value if (sym != s_lparen) expectedchar(s_lparen); getsym(); // eat '(' vpush(getarg(getnum())); if (sym != s_rparen) expectedchar(s_rparen); getsym(); // eat ')' break; case s_lparen: // expression in parens getexpression(); if (exptype != s_nval) expected(M_number); if (sym != s_rparen) missing(M_rparen); vpush(expval); getsym(); // eat the ) break; // // The Family of Unary Operators, which Bind Most Closely to their Factor // case s_add: // unary plus (like +3) is kind of a no-op getfactor(); // scan a factor and leave its result on the stack break; // done case s_sub: // unary minus (like -3) getfactor(); vpush(-vpop()); // similar to above but we adjust the stack value break; case s_bitnot: getfactor(); vpush(~vpop()); break; case s_logicalnot: getfactor(); vpush(!vpop()); break; case s_bitand: // &var gives address-of-var; ¯o gives eeprom address of macro if (sym == s_nvar) vpush((numvar) &vars[symval]); else if (sym == s_script_eeprom) vpush(symval); else expected(M_var); getsym(); // eat the var reference break; case s_mul: // *foo is contents-of-address-foo; *foo=bar is byte poke assignment /***** // what is really acceptable for an lvalue here? ;) // *y = 5 is failing now by assigning 5 to y before the * is dereferenced // due to calling getfactor // everything else works :( *****/ getfactor(); #if 0 if (sym == s_equals) { getsym(); // eat '=' getexpression(); * (volatile byte *) vpop() = (byte) expval; vpush((numvar) (byte) expval); } else #endif vpush((numvar) (* (volatile byte *) vpop())); break; default: unexpected(M_number); } }
// Look up an entry by key. Returns -1 on fail else addr of value. int getValue(char *key) { int kaddr = findKey(key); return (kaddr < 0) ? kaddr : findend(kaddr); }
static int parse_http_request(char * data, int len, char * url) { const char * p = data; char * tail = p + len; const char * uri_data = NULL; int uri_len = 0; const char * host_data = NULL; int host_len = 0; int flag_find = 0; // POST / HTTP/1.0$$$$ // GET / HTTP/1.0$$$$ minimum // 0123456789012345678 // 9876543210 if (((p = findend(data, tail, 18)) == NULL) || (memcmp(p - 9, " HTTP/", 6) != 0)) { return -1; } // save uri to buf uri_data = data + 4; //get_strip_string(WEBFILTER_STR_URI, &uri_data, p - 9, &uri_len); // support '?' in uri if (get_strip_uri(&uri_data, p - 9, &uri_len)) { return -1; } //printf("urI len : %4d\n", uri_len); while (1) { // find all info, so break if (1 == flag_find) { break; } data = p + 2; // skip previous \r\n p = findend(data, tail, 8); // p = current line's \r if (p == NULL) { break; } if (0 == memcmp(data, "Host: ", 6)) { host_data = data + 6; get_strip_string(WEBFILTER_STR_HOST, &host_data, p, &host_len); if (host_len >= MAX_URL_LEN) { LOG("%s, host(size:%d) is too long!\n", __FUNCTION__, host_len); return -1; } if (host_len + uri_len >= MAX_URL_LEN) { LOG("%s, url(size:%d) is too long!\n", __FUNCTION__, host_len + uri_len); return -1; } memcpy(url, host_data, host_len); memcpy(url + host_len, uri_data, uri_len); url[host_len + uri_len] = '\0'; printf("urL len : %4d, urL str : %s\n", host_len + uri_len, url); flag_find = 1; } } return 0; }
int main (int argc, char *argv[]) { int cl_sfd,adm_sfd, s,u; int efd; char small_buf[10]; struct epoll_event event; struct epoll_event event2; struct epoll_event *events; struct ev_conn *tmpptr=NULL; struct rlimit limit; long maxfd = MAX_FD; //allocate and check memory limit.rlim_cur = maxfd; limit.rlim_max = maxfd; if ( setrlimit( RLIMIT_NOFILE, &limit ) == -1 ) { perror( "unable to set new soft limit" ); return 1; } /* obtain hard/soft limit */ if ( getrlimit( RLIMIT_NOFILE, &limit ) == -1 ) { perror( "unable to obtain limits" ); return 1; } else { printf( "FD limit = { hard : %d, soft : %d }\n", limit.rlim_max, limit.rlim_cur ); } ev_conn_ptr=(struct ev_conn *) malloc(sizeof(struct ev_conn)*MAX_CLIENTS); if (ev_conn_ptr == NULL) { fprintf(stderr,"malloc can't allocate memory !!!"); return 0; } // //bind on the client port fprintf(stderr,"Binding on the client port...\n"); cl_sfd = create_and_bind (CLIENT_PORT); if (cl_sfd == -1) abort(); s = make_socket_non_blocking (cl_sfd); if (s == -1) abort(); s = listen (cl_sfd, SOMAXCONN); if (s == -1) { perror ("listen"); abort(); } efd = epoll_create1 (0); if (efd == -1) { perror ("epoll_create"); abort(); } fprintf(stderr,"Client sfd %d\n",cl_sfd); event.data.ptr = fd_alloc(cl_sfd);; // event.data.u64 = 0; // event.data.u32 = 0; event.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, cl_sfd, &event); if (s == -1) { perror ("epoll_ctl"); abort(); } //bind on the admin port fprintf(stderr,"Binding on the admin port...\n"); adm_sfd = create_and_bind (ADMIN_PORT); if (adm_sfd == -1) abort(); s = make_socket_non_blocking (adm_sfd); if (s == -1) abort(); s = listen (adm_sfd, SOMAXCONN); if (s == -1) { perror ("listen"); abort(); } fprintf(stderr,"Admin sfd %d\n",adm_sfd); event2.data.ptr = fd_alloc(adm_sfd); // event2.data.u64 = 0; // event2.data.u32 = 0; event2.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, adm_sfd, &event2); if (s == -1) { perror ("epoll_ctl"); abort(); } /* Buffer where events are returned */ events = calloc (MAXEVENTS, sizeof event); /* The event loop */ while (1) { int n, i; n = epoll_wait (efd, events, MAXEVENTS, -1); for (i = 0; i < n; i++) { struct fd *tmpfd=events[i].data.ptr; fprintf(stderr,"wait stopped with %d events fd %d\n",n,tmpfd->sock); //continue; if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || (!(events[i].events & EPOLLIN))) { /* An error has occured on this fd, or the socket is not ready for reading (why were we notified then?) */ fprintf (stderr, "epoll error closing the socket or not error maybe\n"); fd_close(tmpfd); continue; } else if (adm_sfd == tmpfd->sock) { fprintf(stderr,"admin connection\n"); /* We have a notification on the listening socket, which means one or more incoming connections. */ while (1) { struct fd *allocfd=NULL; struct sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; in_len = sizeof in_addr; infd = accept (adm_sfd, &in_addr, &in_len); if (infd == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* We have processed all incoming connections. */ break; } else { perror ("accept"); break; } } //TODO da comentiram dolniq zapis, poneje e izlishen ama sega za debug 6te go ostavq s = getnameinfo (&in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV); if (s == 0) { printf("Accepted Admin connection on descriptor %d " "(host=%s, port=%s)\n", infd, hbuf, sbuf); } /* Make the incoming socket non-blocking and add it to the list of fds to monitor. */ s = make_socket_non_blocking (infd); if (s == -1) abort(); allocfd=fd_alloc(infd); allocfd->is_admin=1; event.data.ptr = allocfd; //event.data.u32 = 1; event.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event); if (s == -1) { perror ("epoll_ctl"); abort(); } } continue; } else if (cl_sfd == tmpfd->sock) { fprintf(stderr,"client connection\n"); /* We have a notification on the listening socket, which means one or more incoming connections. */ while (1) { struct sockaddr in_addr; socklen_t in_len; int infd; char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; in_len = sizeof in_addr; infd = accept (cl_sfd, &in_addr, &in_len); if (infd == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { /* We have processed all incoming connections. */ break; } else { perror ("accept"); break; } } //TODO da comentiram dolniq zapis, poneje e izlishen ama sega za debug 6te go ostavq s = getnameinfo (&in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV); if (s == 0) { printf("Accepted Client connection on descriptor %d " "(host=%s, port=%s)\n", infd, hbuf, sbuf); } /* Make the incoming socket non-blocking and add it to the list of fds to monitor. */ s = make_socket_non_blocking (infd); if (s == -1) abort(); event.data.ptr = fd_alloc(infd); event.events = EPOLLIN | EPOLLET; s = epoll_ctl (efd, EPOLL_CTL_ADD, infd, &event); if (s == -1) { perror ("epoll_ctl"); abort(); } } continue; } else { /* We have data on the fd waiting to be read. Read and display it. We must read whatever data is available completely, as we are running in edge-triggered mode and won't get a notification again for the same data. */ int done = 0; fprintf(stderr,"check\n"); if(tmpfd->is_admin)//admin socket { ssize_t count=0; int local_ptr=-1; int buf_i=0; if(tmpfd->buffer==NULL) { tmpfd->buffer=ev_buffer_alloc(BUFFER_SIZE); tmpfd->buffer->len=0; } fprintf(stderr,"buffer ne e null\n"); char *buf=tmpfd->buffer->buf; while (1) { if(tmpfd->buffer->len>=BUFFER_SIZE) { fprintf(stderr,"max buffer size reached\n"); done=1; break; } count = read (tmpfd->sock, buf+tmpfd->buffer->len, (BUFFER_SIZE-tmpfd->buffer->len)); fprintf(stderr,"4ete ot admin\n"); write(0,buf+tmpfd->buffer->len,count); if (count == -1) { /* If errno == EAGAIN, that means we have read all data. So go back to the main loop. */ if (errno != EAGAIN) { perror ("read"); done = 1; } break; } else if (count == 0) { /* End of file. The remote has closed the connection. */ done = 1; break; } tmpfd->buffer->len+=count; fprintf(stderr,"tmpfd->buffer->len e %d\n",tmpfd->buffer->len); /* Write the buffer to standard output */ if(tmpfd->cur_ptr<0) { if(buf[0]=='\n' || buf[0]=='\r') // new key { u=0; while(u<ERROR_LOOP) //TODO to fix this da po4ne da 4isti socketite kogato sa na 80% pulni { fprintf(stderr,"vleze v cikula i vurti u\n"); cur_ptr++; if(cur_ptr==MAX_CLIENTS) { cur_ptr=1; u++; } tmpptr=ev_conn_ptr+cur_ptr; if(!tmpptr->sock && tmpptr->buffer==NULL) { fprintf(stderr,"cur_ptr e %d\n",cur_ptr); sprintf(small_buf, "%d", cur_ptr); //key generation fprintf(stderr,"small_buf e %s\n",small_buf); write(tmpfd->sock,small_buf,strlen(small_buf)); fprintf(stderr,"brum2\n"); //tmpfd->cur_ptr=cur_ptr; //adding the socket to the memory //tmpptr->sock=tmpfd->sock; break; } } if(u==ERROR_LOOP) { fprintf(stderr,"no free fds\n"); write(tmpfd->sock,"ERROR",5); //TODO to send reconnect signals to the clients and to free the all fds abort(); } fprintf(stderr,"key %d\n",cur_ptr); done=1; break; } else { fprintf(stderr,"chete admina kum koi client 6te se vurje\n"); // write (0, buf, count); for(buf_i=0;buf_i<9 && *(buf+buf_i)!='\n' && *(buf+buf_i)!='\r';buf_i++)small_buf[buf_i]=*(buf+buf_i); small_buf[buf_i]='\0'; local_ptr=strtol(small_buf, NULL, 10); fprintf(stderr,"local_ptr se okaza %d\n",local_ptr); tmpfd->buffer->offset=(buf_i+1); if(tmpfd->buffer->offset>tmpfd->buffer->len) { fprintf(stderr,"ERROR , the offset is bigger than the len.This should not happen\n"); return -1; } if(!local_ptr || local_ptr>MAX_CLIENTS) { fprintf(stderr,"ERROR wrong number\n"); write(tmpfd->sock,"ERROR",5); close(tmpfd->sock); tmpfd->sock=0; break; //error } tmpfd->cur_ptr=local_ptr; fprintf(stderr,"DEBUG count %d\n",count); fprintf(stderr,"DEBUG buf_i %d\n",buf_i); } } } if (done) { if((tmpfd->cur_ptr)>=0) { tmpptr=ev_conn_ptr+tmpfd->cur_ptr; //buf[count]='\0';//TODO tova da go vidq dali nqma da otreje posledniq symbol if(tmpptr->sock) { fprintf(stderr,"ima clientski socket za %d i pi6e v nego\n",tmpfd->cur_ptr); s = write (tmpptr->sock, tmpfd->buffer->buf+tmpfd->buffer->offset, tmpfd->buffer->len-tmpfd->buffer->offset); s = write (0, tmpfd->buffer->buf+tmpfd->buffer->offset, tmpfd->buffer->len-tmpfd->buffer->offset); if (s == -1) { perror ("write"); write(tmpfd->sock,"ERROR",5); close(tmpfd->sock); tmpfd->sock=0; //nikov if(tmpptr->sock){close(tmpptr->sock);tmpptr->sock=0;} ev_buffer_free(tmpfd->buffer); tmpfd->buffer=NULL; break; } //closing the client socket if(tmpptr->sock)close(tmpptr->sock); tmpptr->sock=0; ev_buffer_free(tmpfd->buffer); tmpfd->buffer=NULL; //if(tmpptr->buffer!=NULL)ev_buffer_free(tmpptr->buffer); } else { fprintf(stderr,"zapisva v buffer za %d golqm %d,\n",tmpfd->cur_ptr,tmpfd->buffer->len); tmpptr->buffer=tmpfd->buffer; } } printf ("Closed connection on descriptor %d\n", tmpfd->sock); /* Closing the descriptor will make epoll remove it from the set of descriptors which are monitored. */ tmpfd->buffer=NULL; close (tmpfd->sock); } } else // client socket { char buf[BUFFER_SIZE]; long int local_ptr=-1; int buf_i=0; int tmp=0; int i=0; int error=0; ssize_t count; while (1) { ssize_t count; count = read (tmpfd->sock, buf,BUFFER_SIZE); fprintf(stderr,"client count %d\n",count); if (count == -1) { /* If errno == EAGAIN, that means we have read all data. So go back to the main loop. */ if (errno != EAGAIN) { perror ("read"); done = 1; } break; } else if (count == 0) { /* End of file. The remote has closed the connection. */ done = 1; break; } if (strncmp(buf,"GET ",4)) { break; } for(i=0;i<count;i++) { fprintf(stderr,"%c %d\n",buf[i],i); if(buf[i]=='\r' || buf[i]=='\n') { break; } } if(i==count) { fprintf(stderr,"strange error in http protocol\n"); fd_close(tmpfd); break; } fprintf(stderr,"i e %d\n",i); count=i; if(count <5) { fprintf(stderr,"ERROR count out of boundaries\n"); error=1; break; } fprintf(stderr,"buf+4 e %c\n",*(buf+4)); buf_i=findend(buf+4,count); fprintf(stderr,"bif_i e %d\n",buf_i); buf[buf_i+4]='\0'; tmp=buf_i; for(;buf[buf_i+4]!='/' && buf_i>0;buf_i--); if((tmp-(buf_i+1))>9) { fprintf(stderr,"ERROR count out of boundaries 2\n"); error=1; break; } tmp=0; local_ptr = strtol(buf+4+buf_i+1, NULL, 10); fprintf(stderr,"local_ptr e %lld\n",local_ptr); if(local_ptr==0) { fprintf(stderr,"ERROR local_ptr is 0 for some reason\n"); error=1; break; } if(local_ptr>MAX_CLIENTS) { fprintf(stderr,"ERROR local_ptr %ld",local_ptr); error=1; break; } tmpptr=ev_conn_ptr+local_ptr; if(tmpptr->sock) { fprintf(stderr,"ERROR tmpptr->sock %d",tmpptr->sock); error=1; break; } tmpptr->sock=tmpfd->sock; tmpfd->cur_ptr=local_ptr; done=1; } if(error) { s = write (tmpfd->sock, HEADER_BUSY, HEADER_LEN_BUSY); fd_close(tmpfd);tmpfd->sock=0; } else if (done && tmpfd->cur_ptr!=-1) { tmpptr=ev_conn_ptr+tmpfd->cur_ptr; s = write (tmpptr->sock, HEADER, HEADER_LEN); if(tmpptr->buffer!=NULL) { fprintf(stderr,"buffer ne e NULL len e %d\n",tmpptr->buffer->len); fprintf(stderr,"offset\n"); fprintf(stderr,"buffer ne e NULL offset e %d\n",tmpptr->buffer->offset); //for(i=0;i<tmpptr->buffer->len;i++)fprintf(stderr,"%c %d\n",tmpptr->buffer->buf); s = write (tmpptr->sock, tmpptr->buffer->buf+tmpptr->buffer->offset, tmpptr->buffer->len-tmpptr->buffer->offset); write(0,tmpptr->buffer->buf+tmpptr->buffer->offset,tmpptr->buffer->len-tmpptr->buffer->offset); fprintf(stderr,"close\n"); fd_close(tmpfd); tmpptr->sock=0; fprintf(stderr,"sock 0\n"); ev_buffer_free(tmpptr->buffer); fprintf(stderr,"free\n"); tmpptr->buffer=NULL; } } else if(done) { fprintf(stderr,"nqma cur_ptr i e done taka 4e zatvarq conneciqta\n"); fd_close(tmpfd);tmpfd->sock=0; } } } } } free (events); close (adm_sfd); close (cl_sfd); return EXIT_SUCCESS; }