listen_ecb.do_read = do_accept; listen_ecb.do_write = NULL; listen_ecb.bufs = NULL; int kq = kqueue(); ke_change (sock, EVFILT_READ, EV_ADD | EV_ENABLE, &listen_ecb); } static void ke_change (int const ident,int const filter, int const flags, void *const udata){ enum { initial_alloc = 1024 }; struct kevent *kep; if (!ke_vec_alloc){ ke_vec_alloc=initial_alloc; ke_vec=(struct kevent*)malloc(ke_vec_alloc*sizeof (struct kevent)); }else if (ke_vec_used == ke_vec_alloc){ ke_vec_alloc<<=1; ke_vec=(struct kevent*)realloc(ke_vec, ke_vec_alloc*sizeof(struct kevent)); } kep = &ke_vec[ke_vec_used++]; kep->ident = ident; kep->filter = filter; kep->flags = flags; log_printf("ke_change socket=%d filter=%s flags=0x%04x (%s%s%s%s%s%s%s%s), ", kep->ident, (kep->filter==EVFILT_READ?"EVFILT_READ":"EVFILT_WRITE"), flags, (flags & EV_EOF) ? "EV_EOF" : "", (flags & EV_ERROR) ? ((flags & (~(EV_ERROR - 1) & ~EV_ERROR)) ? " | EV_ERROR" : "EV_ERROR") : "", (flags & EV_ADD) ? ((flags & (EV_SYSFLAGS | (EV_ADD - 1))) ? " | EV_ADD" : "EV_ADD") : "", (flags & EV_DELETE) ? ((flags & (EV_SYSFLAGS | (EV_DELETE - 1))) ? " | EV_DELETE" : "EV_DELETE") : "", (flags & EV_ENABLE) ? ((flags & (EV_SYSFLAGS | (EV_ENABLE - 1))) ? " | EV_ENABLE" : "EV_ENABLE") : "", (flags & EV_DISABLE) ? ((flags & (EV_SYSFLAGS | (EV_DISABLE - 1))) ? " | EV_DISABLE" : "EV_DISABLE") : "", (flags & EV_ONESHOT) ? ((flags & (EV_SYSFLAGS | (EV_ONESHOT - 1))) ? " | EV_ONESHOT" : "EV_ONESHOT") : "", (flags & EV_CLEAR) ? ((flags & (EV_SYSFLAGS | (EV_CLEAR - 1))) ? " | EV_CLEAR" : "EV_CLEAR") : "" ); kep->fflags = 0; kep->data = 0; kep->udata = udata; } void unistall_connect(ecb *ecbp){ ke_change(ecbp->ident, EVFILT_READ, EV_DELETE, NULL); ke_change(ecbp->ident, EVFILT_WRITE, EV_DELETE, NULL); // ke_change(ecbp->ident, EVFILT_WRITE, EV_CLEAR, (void*)1); // ke_change(ecbp->ident, EVFILT_READ, EV_CLEAR, (void*)1); close(ecbp->ident); free_msgs(ecbp); free(ecbp->bufs); free(ecbp->bufsiz); XML_ParserFree(ecbp->parser); free(ecbp); } static void event_loop (int const kq){ while(1){ int n; struct kevent const *kep; ke_vec_ghost = ke_vec_used; log_printf("kevent() ke_vec_used = %d",ke_vec_used); n = kevent (kq, ke_vec, ke_vec_used, ke_vec, ke_vec_alloc, NULL); log_printf("%d events recieved :)",n); ke_vec_used = 0; if (n == -1) log_printf("Error in kevent(): %s", strerror (errno)); if (n == 0) log_printf("No events received!"); for (kep = ke_vec; kep < &ke_vec[n]; kep++){ if(!kep->udata) continue; //костылик log_printf("event socket %d: %s",kep->ident,(kep->filter==EVFILT_READ?"EVFILT_READ":"!EVFILT_READ")); ecb const *const ecbp = (ecb *) kep->udata; if (kep->filter == EVFILT_READ) (*ecbp->do_read) (kep); else (*ecbp->do_write) (kep); } } } static void do_read (register struct kevent const *const kep){ enum { bufsize = 1024 }; char buf[bufsize]; int n; ecb *ecbp = (ecb *) kep->udata; if ((n = read (kep->ident, buf, bufsize)) == -1){ log_printf("Error reading socket: %s", strerror (errno)); unistall_connect(ecbp); return; }else if(n == 0){ log_printf("disconnect %s",inet_ntoa(ecbp->sin.sin_addr)); unistall_connect(ecbp); return; } if (XML_Parse(ecbp->parser, buf, n, 0) == XML_STATUS_ERROR) { char *errormsg = calloc(1024, sizeof(char)); sprintf(errormsg, "%s\n", XML_GetCurrentLineNumber(ecbp->parser),XML_ErrorString(XML_GetErrorCode(ecbp->parser))); add_msg(ecbp,errormsg); ecbp->on_error=1; log_printf("disconnect %s on protocol error",inet_ntoa(ecbp->sin.sin_addr)); } } static void do_write(register struct kevent const *const kep){ int n,i; ecb *ecbp = (ecb*) kep->udata; for(i=0;ibufnum;i++){ n = write(kep->ident, ecbp->bufs[i], ecbp->bufsiz[i]); if (n == -1){ log_printf("Error writing socket: %s", strerror (errno)); unistall_connect(ecbp); return; } } if(ecbp->on_error){ unistall_connect(ecbp); return; } free_msgs(ecbp); ke_change(ecbp->ident, EVFILT_WRITE, EV_DISABLE, ecbp); }