int billing_epoll_wait() { int nfds; int i; int ret=0 ; nfds = epoll_wait(kdpfd, events, MAX_EVENTS, EPOLL_TIMEOUT); if(nfds == -1) { if( errno != EINTR ) { return -1; } } else if( 0 == nfds) { return 0; } for (i = 0; i < nfds; i++) { if (listen_fd == events[i].data.fd){ handle_accept(listen_fd); } else if (events[i].events & EPOLLIN){ read_billing_info(events[i].data.fd); } else if (events[i].events & (EPOLLHUP|EPOLLERR)){ disconnect_fd(events[i].data.fd); } } return ret; }
/* * Ends use of the scanner. * * From the SANE spec: * This function terminates the association between the device handle * passed in argument h and the device it represents. If the device is * presently active, a call to sane_cancel() is performed first. After * this function returns, handle h must not be used anymore. */ void sane_close (SANE_Handle handle) { DBG (10, "sane_close: start\n"); sane_cancel(handle); disconnect_fd((struct scanner *) handle); DBG (10, "sane_close: finish\n"); }
/* * Terminates the backend. * * From the SANE spec: * This function must be called to terminate use of a backend. The * function will first close all device handles that still might be * open (it is recommended to close device handles explicitly through * a call to sane_close(), but backends are required to release all * resources upon a call to this function). After this function * returns, no function other than sane_init() may be called * (regardless of the status value returned by sane_exit(). Neglecting * to call this function may result in some resources not being * released properly. */ void sane_exit (void) { struct scanner *dev, *next; DBG (10, "sane_exit: start\n"); for (dev = scanner_devList; dev; dev = next) { disconnect_fd(dev); next = dev->next; free (dev->device_name); free (dev); } if (sane_devArray) free (sane_devArray); scanner_devList = NULL; sane_devArray = NULL; DBG (10, "sane_exit: finish\n"); }
/* callback used by sane_get_devices * build the scanner struct and link to global list * unless struct is already loaded, then pretend */ static SANE_Status attach_one (const char *device_name) { struct scanner *s; int ret, i; SANE_Word vid, pid; DBG (10, "attach_one: start '%s'\n", device_name); for (s = scanner_devList; s; s = s->next) { if (strcmp (s->sane.name, device_name) == 0) { DBG (10, "attach_one: already attached!\n"); return SANE_STATUS_GOOD; } } /* build a scanner struct to hold it */ DBG (15, "attach_one: init struct\n"); if ((s = calloc (sizeof (*s), 1)) == NULL) return SANE_STATUS_NO_MEM; /* copy the device name */ s->device_name = strdup (device_name); if (!s->device_name){ free (s); return SANE_STATUS_NO_MEM; } /* connect the fd */ DBG (15, "attach_one: connect fd\n"); s->fd = -1; ret = connect_fd(s); if(ret != SANE_STATUS_GOOD){ free (s->device_name); free (s); return ret; } /* clean up the scanner struct based on model */ /* this is the only piece of model specific code */ sanei_usb_get_vendor_product(s->fd,&vid,&pid); if(vid == 0x08f0){ s->vendor_name = "CardScan"; if(pid == 0x0005){ s->product_name = "800c"; } else if(pid == 0x0002){ s->product_name = "600c"; } else{ DBG (5, "Unknown product, using default settings\n"); s->product_name = "Unknown"; } } else if(vid == 0x0451){ s->vendor_name = "Sanford"; if(pid == 0x6250){ s->product_name = "800c"; } else{ DBG (5, "Unknown product, using default settings\n"); s->product_name = "Unknown"; } } else{ DBG (5, "Unknown vendor/product, using default settings\n"); s->vendor_name = "Unknown"; s->product_name = "Unknown"; } DBG (15, "attach_one: Found %s scanner %s at %s\n", s->vendor_name, s->product_name, s->device_name); /*copy config file settings*/ s->has_cal_buffer = global_has_cal_buffer; s->lines_per_block = global_lines_per_block; s->color_block_size = s->lines_per_block * PIXELS_PER_LINE * 3; s->gray_block_size = s->lines_per_block * PIXELS_PER_LINE; /* try to get calibration */ if(s->has_cal_buffer){ DBG (15, "attach_one: scanner calibration\n"); ret = load_calibration(s); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: cannot calibrate, incompatible?\n"); free (s->device_name); free (s); return ret; } } else{ DBG (15, "attach_one: skipping calibration\n"); } /* set SANE option 'values' to good defaults */ DBG (15, "attach_one: init options\n"); /* go ahead and setup the first opt, because * frontend may call control_option on it * before calling get_option_descriptor */ memset (s->opt, 0, sizeof (s->opt)); for (i = 0; i < NUM_OPTIONS; ++i) { s->opt[i].name = "filler"; s->opt[i].size = sizeof (SANE_Word); s->opt[i].cap = SANE_CAP_INACTIVE; } s->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS; s->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT; s->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT; DBG (15, "attach_one: init settings\n"); /* we close the connection, so that another backend can talk to scanner */ disconnect_fd(s); /* load info into sane_device struct */ s->sane.name = s->device_name; s->sane.vendor = s->vendor_name; s->sane.model = s->product_name; s->sane.type = "scanner"; s->next = scanner_devList; scanner_devList = s; DBG (10, "attach_one: finish\n"); return SANE_STATUS_GOOD; }
static int read_billing_info( int sock_fd ) { uint32_t billing_count = 0; char msgError[1024]; fde *F = &fd_table[sock_fd]; //static char billing_buff[102400]; //static int32_t left_len = 0; // add by cwg at 2013-07-23 char tmp_buff[102400]; memset(tmp_buff, '\0', 102400); if (F->left_len > 0) { if (F->billing_buff) { memcpy(tmp_buff, F->billing_buff, F->left_len); free(F->billing_buff); F->billing_buff = NULL; } else { addInfoLog(0, "WARING: the left_len large 0,but billing_buff is NULL!"); } } else { if (F->billing_buff) { memset(msgError, '\0', 1024); snprintf(msgError, 1024, "WARING: the left_len == 0, but billing_buff is not NULL! billing_buff:%s", F->billing_buff); addInfoLog(0, msgError); free(F->billing_buff); F->billing_buff = NULL; } } ssize_t len = read(sock_fd, tmp_buff + F->left_len, 10240); if( len == 0) { addInfoLog(0,"in read_billing_info, read_len ==0\n"); goto fail; } else if( (len < 0) && (errno == EINTR) ) { addInfoLog(0,"in read_billing_info, errno == EINTR\n"); return 0; } else if( len < 0 ) { addInfoLog(0,"in read_billing_info, read_len < 0\n"); goto fail; } F->left_len += len; //F->billing_buff[F->left_len] = 0; // add by cwg at 2013-07-23 tmp_buff[F->left_len] = 0; time_t current_time = time(NULL); delta_rcv_time = (int) difftime(current_time, last_rcv_ok); if (delta_rcv_time > 300) { addInfoLog(0, "Warning: billingd not received data over 300 seconds\n"); } else if (delta_rcv_time < 0) { addInfoLog(0, "Warning: the interval of billingd received data is abnormal\n"); } /* i do not find a good resulution for multi-squid */ delta_rcv_time = 12; // fixed me, this is bad !! last_rcv_ok = current_time; addInfoLog(1,tmp_buff); char *tmp; while( (tmp = memchr(tmp_buff, '\n', F->left_len)) != NULL) { char line[1024]; memset(line, 0, 1024); assert((tmp - tmp_buff) < 1024); memcpy(line, tmp_buff, (tmp - tmp_buff)); billing_count++; billing_line(line); tmp++; int cha = tmp - tmp_buff; if(cha < 1) { addInfoLog(0,"in read_billing_info, cha < 1\n"); goto fail; } F->left_len -= cha; memmove(tmp_buff, tmp, F->left_len); tmp_buff[F->left_len] = 0; } // add by cwg at 2013-07-30 不为NULL 代表1 malloc成功了;2 被赋值过 if (F->billing_buff) { free(F->billing_buff); F->billing_buff = NULL; } if (F->left_len > 0) { // add by cwg at 2013-07-29 F->billing_buff = malloc(F->left_len + 1); if (!F->billing_buff) { addInfoLog(0, "error: malloc() for billing_buff fail! so exit(-1)!!"); exit(-1); } memset(F->billing_buff, '\0', F->left_len + 1); memcpy(F->billing_buff, tmp_buff, F->left_len); } if( F->left_len < 0 ) { addInfoLog(2,"[read_socket] left_len < 0"); exit(0); } return 0; fail: addInfoLog(0, "[read_socket] error\n"); disconnect_fd(sock_fd); return -1; }
int rf_epoll_wait(epoll_handle_accept *accept_handler,epoll_handle_read_event *read_handler,epoll_handle_write_event *write_handler){ int nfds; int i; rf_client *rfc; nfds = epoll_wait(kdpfd, events, MAX_EVENTS, EPOLL_TIMEOUT); if(nfds == -1) { if( errno != EINTR ) { cclog(2,"ERROR. {%s}\n", strerror(errno)); return RF_ERR_EPOLL; } return RF_OK; } else if( 0 == nfds) { cclog(9,"epoll timeout!"); return RF_OK; } int ret = -1; int fd; for( i = 0 ; i < nfds ; i++ ) { if( listen_fd == events[i].data.fd ) { accept_handler(listen_fd); continue; } fd = events[i].data.fd; rfc = &fd_table[fd]; if(events[i].events & (EPOLLIN|EPOLLHUP|EPOLLERR)){ ret = read_handler(fd); switch(ret){ case RF_OK: cclog(5,"process success! fd(%d)",fd); break; case RF_ERR_PEER_CLOSE: cclog(2,"close peer socket! close fd(%d),ip(%s)",fd,get_peer_ip(fd)); //add for async report dir refresh result if(rfc->type == RF_CLIENT_REPORT) { rf_set_session_report_status(fd, RF_SESSION_CLOSE); } //add for async report dir refresh result disconnect_fd(fd); break; case RF_CLOSE_REPORT: if(rfc->type == RF_CLIENT_REPORT) { cclog(2, "refreshd close report fd: [%d], peer_ip: [%s]", fd, get_peer_ip(fd)); rf_set_session_report_status(fd, RF_SESSION_SUCCESS); } disconnect_fd(fd); break; default: //add for async report dir refresh result if(rfc->type == RF_CLIENT_REPORT) { rf_set_session_report_status(fd, RF_SESSION_FAILED); } //add for async report dir refresh result cclog(2,"proccess error! close fd(%d),ip(%s),ret(%d)",fd,get_peer_ip(fd),ret); disconnect_fd(fd); break; } } if(events[i].events & (EPOLLOUT|EPOLLHUP|EPOLLERR)){ ret = write_handler(fd); switch(ret){ case RF_OK: cclog(5,"process success! fd(%d),ip(%s)",fd,get_peer_ip(fd)); break; case RF_ERR_PEER_CLOSE: cclog(2,"close peer socket! close fd(%d),ip(%s)",fd,get_peer_ip(fd)); //add for async report dir refresh result if(rfc->type == RF_CLIENT_REPORT) { rf_set_session_report_status(fd, RF_SESSION_SUCCESS); } //add for async report dir refresh result disconnect_fd(fd); break; default: //add for async report dir refresh result rfc = &fd_table[fd]; if(rfc->type == RF_CLIENT_REPORT) { rf_set_session_report_status(fd, RF_SESSION_FAILED); } //add for async report dir refresh result cclog(2,"proccess error! close fd(%d),ip(%s)",fd,get_peer_ip(fd)); disconnect_fd(fd); break; } } } return RF_OK; }