예제 #1
0
void listener_thread(int *fd)
{
     ci_connection_t conn;
     socklen_t claddrlen = sizeof(struct sockaddr_in);
     int haschild = 1, jobs_in_queue = 0;
     int pid, sockfd;
     sockfd = *fd;
     thread_signals(1);
     /*Wait main process to signal us to start accepting requests*/
     ci_thread_mutex_lock(&counters_mtx);
     listener_running = 1;
     ci_thread_cond_wait(&free_server_cond, &counters_mtx);
     ci_thread_mutex_unlock(&counters_mtx);
     pid = getpid();
     for (;;) {                 //Global for
          if (child_data->to_be_killed) {
               ci_debug_printf(5, "Listener of pid:%d exiting!\n", pid);
               goto LISTENER_FAILS_UNLOCKED;
          }
          if (!ci_proc_mutex_lock(&accept_mutex)) {
               if (errno == EINTR) {
                    ci_debug_printf(5,
                                    "proc_mutex_lock interrupted (EINTR received, pid=%d)!\n",
                                    pid);
                    /*Try again to take the lock */
                    continue;
               }
               else {
                    ci_debug_printf(1,
                                    "Unknown errno %d in proc_mutex_lock of pid %d. Exiting!\n",
                                    errno, pid);
                    goto LISTENER_FAILS_UNLOCKED;
               }
          }
          child_data->idle = 0;
          ci_debug_printf(7, "Child %d getting requests now ...\n", pid);
          do {                  //Getting requests while we have free servers.....
#ifndef SINGLE_ACCEPT
               fd_set fds;
               int ret;
               do {
                    FD_ZERO(&fds);
                    FD_SET(sockfd, &fds);
                    errno = 0;
                    ret = select(sockfd + 1, &fds, NULL, NULL, NULL);
                    if (ret < 0) {
                         if (errno != EINTR) {
                              ci_debug_printf(1,
                                              "Error in select %d! Exiting server!\n",
                                              errno);
                              goto LISTENER_FAILS;
                         }
                         if (child_data->to_be_killed) {
                              ci_debug_printf(5,
                                              "Listener server signalled to exit!\n");
                              goto LISTENER_FAILS;
                         }
                    }
               } while (errno == EINTR);
#endif
               do {
                    errno = 0;
                    claddrlen = sizeof(conn.claddr.sockaddr);
                    if (((conn.fd =
                          accept(sockfd,
                                 (struct sockaddr *) &(conn.claddr.sockaddr),
                                 &claddrlen)) == -1)) {
                         if (errno != EINTR && errno != ECONNABORTED) {
                              ci_debug_printf(1,
                                              "Error accept %d!\nExiting server!\n",
                                              errno);
                              goto LISTENER_FAILS;
                         }
                         /*Here we are going to exit only if accept interrupted by a signal
                           else if we accepted an fd we must add it to queue for 
                           processing. */
                         if (errno == EINTR && child_data->to_be_killed) {
                              ci_debug_printf(5,
                                              "Listener server signalled to exit!\n");
                              goto LISTENER_FAILS;
                         } else {
                             ci_debug_printf(2, "Accept failed: errno=%d, ingore!\n", errno);
                         }
                    }
               } while (errno == EINTR && !child_data->to_be_killed);

               // Probably ECONNABORTED or similar error
               if (conn.fd < 0)
                   continue;

               claddrlen = sizeof(conn.srvaddr.sockaddr);
               getsockname(conn.fd,
                           (struct sockaddr *) &(conn.srvaddr.sockaddr),
                           &claddrlen);
               ci_fill_sockaddr(&conn.claddr);
               ci_fill_sockaddr(&conn.srvaddr);

               icap_socket_opts(sockfd, MAX_SECS_TO_LINGER);

               if ((jobs_in_queue = put_to_queue(con_queue, &conn)) == 0) {
                    ci_debug_printf(1,
                                    "ERROR!!!!!! NO AVAILABLE SERVERS! THIS IS A BUG!!!!!!!!\n");
                    ci_debug_printf(1,
                                    "Jobs in Queue: %d, Free servers: %d, Used Servers: %d, Requests: %d\n",
                                    jobs_in_queue, child_data->freeservers,
                                    child_data->usedservers,
                                    child_data->requests);
                    goto LISTENER_FAILS;
               }
               (child_data->connections)++;     //NUM of Requests....

               if (child_data->to_be_killed) {
                   ci_debug_printf(5, "Listener server must exit!\n");
                   goto LISTENER_FAILS;
               }
               ci_thread_mutex_lock(&counters_mtx);
               haschild =
                   ((child_data->freeservers - jobs_in_queue) > 0 ? 1 : 0);
               ci_thread_mutex_unlock(&counters_mtx);
          } while (haschild);
          ci_debug_printf(7, "Child %d STOPS getting requests now ...\n", pid);
          child_data->idle = 1;
          while (!ci_proc_mutex_unlock(&accept_mutex)) {
               if (errno != EINTR) {
                    ci_debug_printf(1,
                                    "Error:%d while trying to unlock proc_mutex, exiting listener of server:%d\n",
                                    errno, pid);
                    goto LISTENER_FAILS_UNLOCKED;
               }
               ci_debug_printf(5,
                               "Mutex lock interrupted while trying to unlock proc_mutex, pid: %d\n",
                               pid);
          }

          ci_thread_mutex_lock(&counters_mtx);
          if ((child_data->freeservers - connections_pending(con_queue)) <= 0) {
               ci_debug_printf(7,
                               "Child %d waiting for a thread to accept more connections ...\n",
                               pid);
               ci_thread_cond_wait(&free_server_cond, &counters_mtx);
          }
          ci_thread_mutex_unlock(&counters_mtx);
     }
   LISTENER_FAILS_UNLOCKED:
     listener_running = 0;
     return;

   LISTENER_FAILS:
     listener_running = 0;
     errno = 0;
     while (!ci_proc_mutex_unlock(&accept_mutex)) {
          if (errno != EINTR) {
               ci_debug_printf(1,
                               "Error:%d while trying to unlock proc_mutex of server:%d\n",
                               errno, pid);
               break;
          }
          ci_debug_printf(7,
                          "Mutex lock interrupted while trying to unlock proc_mutex before terminating\n");
     }
     return;
}
예제 #2
0
파일: header.c 프로젝트: p1rate5s/c-icap
int ci_headers_unpack(ci_headers_list_t * h)
{
     int len, eoh;
     char **newspace;
     char *shead, *ebuf, *str;

     if (h->bufused < 2)        /*???????????? */
          return EC_400;

     ebuf = h->buf + h->bufused - 2;
     /* ebuf now must indicate the last \r\n so: */
     if (*ebuf != '\r' && *ebuf != '\n') {      /*Some sites return (this is bug ) a simple '\n' as end of header ..... */
          ci_debug_printf(3,
                          "Parse error. The end chars are %c %c (%d %d) not the \\r \n",
                          *ebuf, *(ebuf + 1), (unsigned int) *ebuf,
                          (unsigned int) *(ebuf + 1));
          return EC_400;        /*Bad request .... */
     }
     *ebuf = '\0';
     shead = h->buf;

     h->headers[0] = h->buf;
     h->used = 1;

     for (str = h->buf; str < ebuf; str++) {    /*Construct index of headers */
          eoh = 0;

          if ((*str == '\r' && *(str + 1) == '\n')) {
               if ((str + 2) >= ebuf
                   || (*(str + 2) != '\t' && *(str + 2) != ' '))
                    eoh = 1;
          }
          else if (*str == '\n' && *(str + 1) != '\t' && *(str + 1) != ' ') {
               /*handle the case that headers seperated with a '\n' only */
               eoh = 1;
          }
          else if (*str == '\0')        /*Then we have a problem. This char is important for us. Yes can happen! */
               *str = ' ';

          if (eoh) {
               *str = '\0';
               if (h->size <= h->used) {        /*  Resize the headers index space ........ */
                    len = h->size + HEADERSTARTSIZE;
                    newspace = realloc(h->headers, len * sizeof(char *));
                    if (!newspace) {
                         ci_debug_printf(1,
                                         "Server Error: Error allocating memory \n");
                         return EC_500;
                    }
                    h->headers = newspace;
                    h->size = len;
               }
               str++;
               if (*str == '\n')
                    str++;      /*   handle the case that headers seperated with a '\n' only */
               h->headers[h->used] = str;
               h->used++;
          }	  
     }     
     h->packed = 0;
                     /*OK headers index construction ...... */
     return EC_100;
}
예제 #3
0
void free_time_data(ci_request_t *req,void *param)
{
    /*Nothing to do*/
    ci_debug_printf(5, "free_time_data(req=%p, param=%p)", req, param);
    ci_buffer_free(param);
}
예제 #4
0
int create_child(PROCESS_INFORMATION * pi, HANDLE * pipe)
{
     STARTUPINFO si;
     SECURITY_ATTRIBUTES saAttr;
     HANDLE hChildStdinRd, hChildStdinWr, hChildStdinWrDup, hSaveStdin;
     ZeroMemory(&si, sizeof(si));
     si.cb = sizeof(si);

     ZeroMemory(pi, sizeof(PROCESS_INFORMATION));

// Set the bInheritHandle flag so pipe handles are inherited. 
     saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
     saAttr.bInheritHandle = TRUE;
     saAttr.lpSecurityDescriptor = NULL;


// Save the handle to the current STDIN. 

     hSaveStdin = GetStdHandle(STD_INPUT_HANDLE);

// Create a pipe for the child process's STDIN. 

     if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {
          printf("Stdin pipe creation failed\n");
          return 0;
     }

// Set a read handle to the pipe to be STDIN. 

     if (!SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd)) {
          printf("Redirecting Stdin failed");
          return 0;
     }

// Duplicate the write handle to the pipe so it is not inherited. 

     if (!DuplicateHandle(GetCurrentProcess(), hChildStdinWr, GetCurrentProcess(), &hChildStdinWrDup, 0, FALSE, // not inherited 
                          DUPLICATE_SAME_ACCESS)) {
          ci_debug_printf(1, "DuplicateHandle failed");
          return 0;
     }
     CloseHandle(hChildStdinWr);
     *pipe = hChildStdinWrDup;

     ci_debug_printf(1, "Going to start a child...\n");
     // Start the child process. 

     if (!CreateProcessW(NULL,  // No module name (use command line). 
                         C_ICAP_CMD,    // Command line. 
                         NULL,  // Process handle not inheritable. 
                         NULL,  // Thread handle not inheritable. 
                         TRUE,  // Set handle inheritance to TRUE. 
                         0,     // No creation flags. 
                         NULL,  // Use parent's environment block. 
                         NULL,  // Use parent's starting directory. 
                         &si,   // Pointer to STARTUPINFO structure.
                         pi)    // Pointer to PROCESS_INFORMATION structure.
         ) {
          ci_debug_printf(1, "CreateProcess failed. (error:%d)\n",
                          GetLastError());
          return 0;
     }

     if (!SetStdHandle(STD_INPUT_HANDLE, hSaveStdin))
          printf("Re-redirecting Stdin failed\n");
     ci_debug_printf(1, "OK created....\n");
     return 1;
}
예제 #5
0
int do_child()
{
     HANDLE hStdin, child_handle, parent_pipe;
     DWORD dwRead;
     WSAPROTOCOL_INFO sock_info;
     ci_socket sock_fd;

     hStdin = GetStdHandle(STD_INPUT_HANDLE);
     if ((hStdin == INVALID_HANDLE_VALUE))
          ExitProcess(1);

//   ReadFile(hStdin, buf, 512, &dwRead, NULL); 
//   printf("Reading \"%s\" from server\n",buf);

//   sscanf(buf,"%d:%d:%d:%d:%d",&child_handle,&accept_mutex,
//                          &(childs_queue.shmid),&(childs_queue.queue_mtx),
//        &(childs_queue.size));

     if (!ReadFile(hStdin, &child_handle, sizeof(HANDLE), &dwRead, NULL)
         || dwRead != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error reading handles.....\n");
          exit(0);
     }

     if (!ReadFile(hStdin, &parent_pipe, sizeof(HANDLE), &dwRead, NULL)
         || dwRead != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error reading handles.....\n");
          exit(0);
     }

     if (!ReadFile(hStdin, &accept_mutex, sizeof(HANDLE), &dwRead, NULL)
         || dwRead != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error reading handles.....\n");
          exit(0);
     }
     if (!ReadFile(hStdin, &(childs_queue.shmid), sizeof(HANDLE), &dwRead, NULL)
         || dwRead != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error reading handles.....\n");
          exit(0);
     }
     if (!ReadFile
         (hStdin, &(childs_queue.queue_mtx), sizeof(HANDLE), &dwRead, NULL)
         || dwRead != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error reading handles.....\n");
          exit(0);
     }
     if (!ReadFile(hStdin, &(childs_queue.size), sizeof(int), &dwRead, NULL) ||
         dwRead != sizeof(int)) {
          ci_debug_printf(1, "Error reading handles.....\n");
          exit(0);
     }

     if (!ReadFile
         (hStdin, &(sock_info), sizeof(WSAPROTOCOL_INFO), &dwRead, NULL)
         || dwRead != sizeof(WSAPROTOCOL_INFO)) {
          ci_debug_printf(1, "Error reading handles.....\n");
          exit(0);
     }

     if ((sock_fd = WSASocket(FROM_PROTOCOL_INFO,
                              FROM_PROTOCOL_INFO,
                              FROM_PROTOCOL_INFO,
                              &(sock_info), 0, 0)) == INVALID_SOCKET) {
          ci_debug_printf(1, "Error in creating socket :%d\n",
                          WSAGetLastError());
          return 0;
     }


     if (!attach_childs_queue(&childs_queue)) {
          ci_debug_printf(1, "Error in new child .....\n");
          return 0;
     }
     ci_debug_printf(1, "Shared memory attached....\n");
     child_data =
         register_child(&childs_queue, child_handle, START_SERVERS,
                        parent_pipe);
     ci_debug_printf(1, "child registered ....\n");

     child_main(sock_fd);
     exit(0);
}
예제 #6
0
/*
  maybe the wdata must moved to the ci_request_t and write_to_module_pending must replace wdata_len
*/
int parse_chunk_data(ci_request_t * req, char **wdata)
{
     char *end;
     int num_len, remains, tmp;
     int read_status = 0;

     *wdata = NULL;
     if (req->write_to_module_pending) {
          /*We must not here if the chunk buffer did not flashed */
          return CI_ERROR;
     }

     while (1) {
          if (req->current_chunk_len == req->chunk_bytes_read)
               read_status = READ_CHUNK_DEF;
          else
               read_status = READ_CHUNK_DATA;

          if (read_status == READ_CHUNK_DEF) {
               errno = 0;
               tmp = strtol(req->pstrblock_read, &end, 16);
               /*here must check for erron */
               if (tmp == 0 && req->pstrblock_read == end) {    /*Oh .... an error ... */
                    ci_debug_printf(5, "Parse error:count=%d,start=%c\n",
                                    tmp, req->pstrblock_read[0]);
                    return CI_ERROR;
               }
               num_len = end - req->pstrblock_read;
               if (req->pstrblock_read_len - num_len < 2) {
                    return CI_NEEDS_MORE;
               }
               /*At this point the req->pstrblock_read must point to the start of a chunk eg to a "123\r\n" */
               req->chunk_bytes_read = 0;
               req->current_chunk_len = tmp;

               if (req->current_chunk_len == 0) {

                    if (*end == ';') {
                         if (req->pstrblock_read_len < 11) {    /*must hold a 0; ieof\r\n\r\n */
                              return CI_NEEDS_MORE;
                         }

                         if (strncmp(end, "; ieof", 6) != 0)
                              return CI_ERROR;

                         req->eof_received = 1;
                         return CI_EOF;
                    }
                    else {
                         if (req->pstrblock_read_len - num_len < 4) {
                              return CI_NEEDS_MORE;
                         }
                         if (strncmp(end, "\r\n\r\n", 4) != 0)
                              return CI_ERROR;

                         req->pstrblock_read = NULL;
                         req->pstrblock_read_len = 0;
                         return CI_EOF;
                    }
               }
               else {
                    if (*end != '\r' || *(end + 1) != '\n') {
                         return CI_ERROR;
                    }
                    read_status = READ_CHUNK_DATA;
                    req->pstrblock_read = end + 2;
                    req->pstrblock_read_len -= (num_len + 2);
                    /*include the \r\n end of chunk data */
                    req->current_chunk_len += 2;
               }
          }
          /*if we have data for service leaving this function now */
          if (req->write_to_module_pending)
               return CI_OK;
          if (read_status == READ_CHUNK_DATA) {
               if (req->pstrblock_read_len <= 0) {
                    return CI_NEEDS_MORE;
               }
               *wdata = req->pstrblock_read;
               remains = req->current_chunk_len - req->chunk_bytes_read;
               if (remains <= req->pstrblock_read_len) {        /*we have all the chunks data */
		 if (remains > 2) {
                         req->write_to_module_pending = remains - 2;
			 req->http_bytes_in += req->write_to_module_pending;
			 req->body_bytes_in += req->write_to_module_pending;
		 } 
		 else        /*we are in all or part of the \r\n end of chunk data */
                         req->write_to_module_pending = 0;
                    req->chunk_bytes_read += remains;
                    req->pstrblock_read += remains;
                    req->pstrblock_read_len -= remains;
               }
               else {
                    tmp = remains - req->pstrblock_read_len;
                    if (tmp < 2) {
                         req->write_to_module_pending =
                             req->pstrblock_read_len - tmp;
			 req->http_bytes_in += req->write_to_module_pending;
			 req->body_bytes_in += req->write_to_module_pending;
                    }
                    else {
                         req->write_to_module_pending = req->pstrblock_read_len;
			 req->http_bytes_in += req->write_to_module_pending;
			 req->body_bytes_in += req->write_to_module_pending;
		    }
                    req->chunk_bytes_read += req->pstrblock_read_len;
                    req->pstrblock_read += req->pstrblock_read_len;
                    req->pstrblock_read_len -= req->pstrblock_read_len;
               }
          }
          if (req->pstrblock_read_len == 0)
               return CI_NEEDS_MORE;
     }

     return CI_OK;
}
예제 #7
0
int thread_main(server_decl_t * srv)
{
     ci_connection_t con;
     char clientname[CI_MAXHOSTNAMELEN + 1];
     int ret, request_status = 0;

//***********************
//     thread_signals();
//*************************
     //    srv->srv_id=getpid(); //Setting my pid ...
     //    srv->srv_pthread=pthread_self();
     for (;;) {
          if (child_data->to_be_killed) {
               ci_debug_printf(1, "Thread exiting.....\n");
               return 1;        //Exiting thread.....
          }

          if ((ret = get_from_queue(con_queue, &con)) == 0) {
               wait_for_queue(con_queue);       //It is better that the wait_for_queue to be 
               //moved into the get_from_queue 
               continue;
          }

          if (ret < 0) {        //An error has occured
               ci_debug_printf(1, "Error getting from connections queue\n");
               break;
          }

          ci_netio_init(con.fd);

          ret = 1;
          if (srv->current_req == NULL)
               srv->current_req = newrequest(&con);
          else
               ret = recycle_request(srv->current_req, &con);

          if (srv->current_req == NULL || ret == 0) {
               ci_sockaddr_t_to_host(&(con.claddr), clientname,
                                     CI_MAXHOSTNAMELEN);
               ci_debug_printf(1, "Request from %s denied...\n", clientname);
               hard_close_connection((&con));
               continue;        /*The request rejected. Log an error and continue ... */
          }


          ci_thread_mutex_lock(&counters_mtx);
          (child_data->freeservers)--;
          (child_data->usedservers)++;
          ci_thread_mutex_unlock(&counters_mtx);

          do {
               if ((request_status = process_request(srv->current_req)) < 0) {
                    ci_debug_printf(1,
                                    "Process request timeout or interupted....\n");
                    break;      //
               }

               srv->served_requests++;
               srv->served_requests_no_reallocation++;

               /*Increase served requests. I dont like this. The delay is small but I don't like... */
               ci_thread_mutex_lock(&counters_mtx);
               (child_data->requests)++;
               ci_thread_mutex_unlock(&counters_mtx);



               log_access(srv->current_req, request_status);
//             break; //No keep-alive ......

               if (child_data->to_be_killed)
                    return 1;   //Exiting thread.....

               ci_debug_printf(1, "Keep-alive:%d\n",
                               srv->current_req->keepalive);
               if (srv->current_req->keepalive
                   && check_for_keepalive_data(srv->current_req->connection->
                                               fd) > 0) {
                    ci_request_reset(srv->current_req);
                    ci_debug_printf(1,
                                    "Server %d going to serve new request from client (keep-alive) \n",
                                    srv->srv_id);
               }
               else
                    break;
          } while (1);

          if (srv->current_req) {
               if (request_status < 0)
                    hard_close_connection(srv->current_req->connection);
               else
                    close_connection(srv->current_req->connection);
          }
          if (srv->served_requests_no_reallocation >
              MAX_REQUESTS_BEFORE_REALLOCATE_MEM) {
               ci_debug_printf(1,
                               "Max requests reached, reallocate memory and buffers .....\n");
               ci_request_destroy(srv->current_req);
               srv->current_req = NULL;
               srv->served_requests_no_reallocation = 0;
          }

          ci_thread_mutex_lock(&counters_mtx);
          (child_data->freeservers)++;
          (child_data->usedservers)--;
          ci_thread_mutex_unlock(&counters_mtx);
          ci_thread_cond_signal(&free_server_cond);

     }
     return 1;
}
예제 #8
0
int ci_format_text(
                 ci_request_t *req_data,
                 const char *fmt,
                 char *buffer, int len,
                 struct ci_fmt_entry *user_table)
{
   const char *s;
   char *b, *lb;
   struct ci_fmt_entry *fmte;
   int directive_len, val_len, remains, left_align, i;
   unsigned int width, space=0;
   char parameter[MAX_VARIABLE_SIZE];

   s = fmt;
   b = buffer;
   remains = len;
   while (*s && remains > 0) {
     if (*s == '%') {
       fmte = check_tables(s, user_table, &directive_len, 
                           &width, &left_align, parameter);
       ci_debug_printf(7,"Width: %d, Parameter:%s\n", width, parameter);
       if (width != 0) 
            space = width = (remains<width?remains:width);
       else
            space = remains;
       if(fmte != NULL) { 
            if (width) {
                if (left_align) {
                    val_len=fmte->format(req_data, b, space, parameter);
                    if (val_len > space) val_len = space;
                    b += val_len;
                    for (i=0; i < width-val_len; i++) b[i]=' ';
                    b += width-val_len;
                }
                else {
                    lb = malloc((space+1)*sizeof(char));      
                    val_len=fmte->format(req_data, lb, space, parameter);
                    if (val_len > space) val_len = space;
                    for (i=0; i < width-val_len; i++) b[i]=' ';
                    b += width-val_len; 
                    for (i=0; i < val_len; i++) b[i]=lb[i];
                    b += val_len;
                    free(lb);
                    lb = NULL;
                }

                remains -= width;
            } 
             else {
		val_len=fmte->format(req_data, b, space, parameter);
                if (val_len > space) val_len = space;
                b += val_len; 
                remains -= val_len;
             }
            s += directive_len;
       }
       else
         *b++ = *s++, remains--; 
     }
     else 
        *b++ = *s++, remains--;
   }
   *b = '\0';
   return len-remains;
}
static void doCoalesce(image_session_t *mySession)
{
CvSeq *newDetected = NULL;
image_detected_t *current;
CvRect tempRect;
int over_left, over_top;
int right1, right2, over_right;
int bottom1, bottom2, over_bottom;
int over_width, over_height;
int r1Area, r2Area;
int *merged = NULL;
int newI = 0;
int i, j;
uint16_t current_category;

	for(current_category = 0; current_category < num_image_categories; current_category++) {
		current = &mySession->detected[current_category];
		if(current->category->coalesceOverlap != 1.0f && current->detected)
		{
			// Loop the number of detected objects
			newDetected = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvRect), mySession->lstorage );
			merged = malloc(sizeof(int) *  current->detected->total);
			newI = 0;
			for(i = 0; i < current->detected->total; i++ ) merged[i] = -1; // quickly setup merged variable
			for(i = 0; i < current->detected->total; i++ )
			{
				CvRect* r = (CvRect*)cvGetSeqElem( current->detected, i );

				if(merged[i] == -1) {
					cvSeqPush( newDetected, r );
					merged[i] = newI;
					newI++;
				}

				if(current->detected->total - i > 0)
				{
					r1Area = r->width * r->height;

					for(j = i + 1; j < current->detected->total; j++ )
					{
						// Reset rectangles to original size
						CvRect* r2 = (CvRect*)cvGetSeqElem( current->detected, j );
						r2Area = r2->width * r2->height;

						right1 = r->x + r->width;
						right2 = r2->x + r2->width;
						bottom1 = r->y + r->height;
						bottom2 = r2->y + r2->height;

						if (!(bottom1 < r2->y) && !(r->y > bottom2) && !(right1 < r2->x) && !(r->x > right2))
						{

							// Ok, compute the rectangle of overlap:
							if (bottom1 > bottom2) over_bottom = bottom2;
							else over_bottom = bottom1;

							if (r->y < r2->y) over_top = r2->y;
							else over_top = r->y;

							if (right1 > right2) over_right = right2;
							else over_right = right1;

							if (r->x < r2->x) over_left = r2->x;
							else over_left = r->x;

							over_width=over_right-over_left;
							over_height=over_bottom-over_top;

							if((r1Area * current->category->coalesceOverlap <= over_width*over_height) || (r2Area * current->category->coalesceOverlap <= over_width*over_height))
							{
								ci_debug_printf(10, "srv_classify_image: Merging detected %s at X: %d, Y: %d, Height: %d, Width: %d and X2: %d, Y2: %d, Height2: %d, Width2: %d\n",
										current->category->name, r->x, r->y, r->height, r->width, r2->x, r2->y, r2->height, r2->width);
								tempRect = cvMaxRect( (CvRect*)cvGetSeqElem( newDetected, merged[i] ), r2);
								cvSeqRemove( newDetected, merged[i] );
								cvSeqInsert( newDetected, merged[i], &tempRect );
								merged[j] = merged[i];
							}
						}
					}
				}
			}
			cvClearSeq( current->detected );
			current->detected = newDetected;
			free(merged);
		}
	}
}
/* This function will be called when the service shutdown */
void search_record_close_service() 
{
	cleanupPairs(&search_engine);
    ci_debug_printf(5,"Search Record Service shutdown!\n");
    /*Nothing to do*/
}
예제 #11
0
int writePREHASHES(int file, HashList *hashes_list)
{
uint32_t i;
uint_least32_t qty = 0;
#ifndef _POSIX_MAPPED_FILES
int writecheck;
#else
struct stat st;
int64_t mmap_offset = 0, size;
char *address;
#endif

#ifdef _POSIX_MAPPED_FILES
	i = ftruncate64(file, (hashes_list->used * PREHASH_SIZE) +  PREHASH_COUNT_SIZE);
	fstat(file, &st);
	size = st.st_size;
	address = mmap(0, size, PROT_WRITE, MAP_SHARED, file, 0);
	if(address == MAP_FAILED)
	{
		ci_debug_printf(3, " writePREHASHES: Failed to mmap with error: %s\n", strerror(errno));
		return -1;
	}
#endif

	if(hashes_list->used) // check before we write
	{
		qty = hashes_list->used;

#ifdef _POSIX_MAPPED_FILES
		binary2char((char *) &qty, address, PREHASH_COUNT_SIZE);
		mmap_offset += PREHASH_COUNT_SIZE;
#else
		do {
			writecheck = write(file, &qty, PREHASH_COUNT_SIZE);
			if(writecheck < PREHASH_COUNT_SIZE) lseek64(file, -writecheck, SEEK_CUR);
		} while (writecheck >=0 && writecheck < PREHASH_COUNT_SIZE);
#endif

		for(i = 0; i < hashes_list->used; i++)
		{
#ifdef _POSIX_MAPPED_FILES
			binary2char((char *) &hashes_list->hashes[i], address + mmap_offset, PREHASH_SIZE);
			mmap_offset += PREHASH_SIZE;
#else
			do { // write hash
				writecheck = write(file, &hashes_list->hashes[i], PREHASH_SIZE);
		                if(writecheck < PREHASH_SIZE) lseek64(file, -writecheck, SEEK_CUR);
			} while (writecheck >=0 && writecheck < PREHASH_SIZE);
#endif
		}
#ifdef _POSIX_MAPPED_FILES
		// wrap up mmap
/*		if(msync(address, size, MS_SYNC) < 0) {
			ci_debug_printf(3, "writeFBCHashes: msync failed with error: %s\n", strerror(errno));
			strerror(errno);
		} */
		if(munmap(address, size) < 0) {
			ci_debug_printf(3, " writePREHASHES: munmap failed with error: %s\n", strerror(errno));

		}
		i = ftruncate64(file, (qty * PREHASH_SIZE) + PREHASH_COUNT_SIZE);
#else
		ftruncate(file, lseek64(file, 0, SEEK_CUR));
#endif
		/* Ok, have written hashes, now save new count */
//		ci_debug_printf(10, "%"PRIu32" hashes, wrote %"PRIu32" hashes\n", hashes_list->used, qty);
		return 0;
	}
	return -1;
}
예제 #12
0
int read_row(FILE *f, int cols, struct text_table_entry **e,
                  struct ci_lookup_table *table)
{
     char line[65536];
     char *s,*val,*end;
     int row_cols,line_len,i;
     ci_mem_allocator_t *allocator = table->allocator;
     ci_type_ops_t *key_ops = table->key_ops;
     ci_type_ops_t *val_ops = table->val_ops;

     (*e)=NULL;

     if(!fgets(line,65535,f))
          return 0;
     line[65535]='\0';
     
     if((line_len=strlen(line))>65535) {
        line[64]='\0';
        ci_debug_printf(1, "Too long line: %s...", line); 
        return 0;
     }
     if(line[line_len-1]=='\n') line[line_len-1]='\0'; /*eat the newline char*/ 

     /*Do a check for comments*/
     s=line;
     while(*s==' ' || *s == '\t') s++;
     if (*s == '#') /*it is a comment*/
         return 1;
     if (*s == '\0') /*it is a blank line */
         return 1;
     if(cols<0) {
         /*the line should have the format  key:val1, val2, ... */
         if (!(s=index(line,':'))) {
             row_cols=1;
         }
         else {
            row_cols=2;
            while((s=index(s,','))) row_cols++,s++;
         }
     }
     else
        row_cols=cols;
    
     (*e) = alloc_text_table_entry(row_cols-1, allocator);
     if(!(*e)) {
	 ci_debug_printf(1,"Error allocating memory for table entry:%s\n", line);
	 return 0;
     }

     s=line;
     while(*s==' ' || *s == '\t') s++;
     val=s; 
    
     end = NULL;
     if (row_cols > 1)
         end=index(s,':');
     if (end == NULL) /*no ":" char or the only column is the key (row_cols <=1)*/
         end=s+strlen(s);

     s=end+1; /*Now points to the end (*s='\0') or after the ':' */

     end--; 
     while(*end==' ' || *end=='\t') end--;
     *(end+1)='\0';
     (*e)->key=key_ops->dup(val, allocator);

     if(!(*e)->key) {
         ci_debug_printf(1, "Error reading key in line:%s\n", line);
         release_text_table_entry((*e), table);
         (*e)=NULL;
         return -1;
     }

     if(row_cols > 1) {
         assert((*e)->vals);
         for (i=0; *s!='\0'; i++) { /*probably we have vals*/
             if(i>=row_cols) {
		 /*here we are leaving memory leak, I think qill never enter this if ...*/
		 ci_debug_printf(1, "Error in read_row of file lookup table!(line:%s)\n", line);
                 release_text_table_entry((*e), table);
                 (*e)=NULL;
		 return -1;
              }

              while(*s==' ' || *s =='\t') s++; /*find the start of the string*/
              val = s; 
              end=s;
              while(*end!=',' && *end!='\0') end++; 
              if (*end=='\0') 
                  s = end;
              else
                  s = end + 1;

              end--;
              while(*end == ' ' || *end == '\t') end--;
              *(end+1)='\0';
              (*e)->vals[i] = val_ops->dup(val, allocator);
          }
	 (*e)->vals[i] = NULL;
     }
     return 1;
}
예제 #13
0
int main(int argc, char **argv){
     int fd_in,fd_out;
     int ret,port=1344;
     char ip[CI_IPLEN];
     ci_connection_t *conn;
     request_t *req;
     ci_headers_list_t *headers;

     CI_DEBUG_LEVEL=1; /*Default debug level is 1*/

     if(!ci_args_apply(argc,argv,options)){
	 ci_args_usage(argv[0],options);
	 exit(-1);
     }

#if ! defined(_WIN32)
     __log_error=(void(*)(void *, const char *,... ))log_errors; /*set c-icap library log  function*/
#else
     __vlog_error=vlog_errors; /*set c-icap library  log function for win32.....*/
#endif


     if(!(conn=ci_client_connect_to(icap_server,port,AF_INET))){
	 ci_debug_printf(1,"Failed to connect to icap server.....\n");
	 exit(-1);
     }

     req=ci_client_request(conn,icap_server,service);

     ci_client_get_server_options(req,CONN_TIMEOUT);
     ci_debug_printf(10,"OK done with options!\n");
     ci_conn_remote_ip(conn,ip);
     ci_debug_printf(1,"ICAP server:%s, ip:%s, port:%d\n\n",icap_server,ip,port);

     if(!input_file){
	  ci_debug_printf(1,"OPTIONS:\n");
	  ci_debug_printf(1,"\tAllow 204: %s\n\tPreview: %d\n\tKeep alive: %s\n",
			  (req->allow204?"Yes":"No"),
			  req->preview,
			  (req->keepalive?"Yes":"No")
	       );
	  print_headers(req);
     }
     else{
	  if((fd_in=open(input_file,O_RDONLY))<0){
	       ci_debug_printf(1,"Error openning file %s\n",input_file);
	       exit(-1);
	  }
	  
	  if(output_file){
	       if((fd_out=open(output_file,O_CREAT|O_RDWR|O_EXCL,S_IRWXU|S_IRGRP))<0){
		    ci_debug_printf(1,"Error opening output file %s\n",output_file);
		    exit(-1);
	       }
	  }
	  else{
	       fd_out=fileno(stdout);
	  }
	  
	  ci_client_request_reuse(req);

	  ci_debug_printf(10,"Preview:%d keepalive:%d,allow204:%d\n",
			  req->preview,req->keepalive,req->allow204);
	  
	  ci_debug_printf(10,"OK allocating request going to send request\n");

	  if(send_headers){
	       headers=ci_headers_make();
	       ci_headers_add(headers,"Filetype: Unknown");
	       ci_headers_add(headers,"User: chtsanti");
	  }
	  else
	       headers=NULL;

	  ret=ci_client_icapfilter(req,
				   CONN_TIMEOUT,
				   headers,
				   &fd_in,(int (*)(void *,char *,int))fileread,
				   &fd_out,(int (*)(void *,char *,int))filewrite
	       );
	  close(fd_in);
	  close(fd_out);

	  if(ret==204){
	       ci_debug_printf(1,"No modification needed (Allow 204 responce)\n");
	       if(output_file)
		    unlink(output_file);
	  }
	  
	  if(verbose)
	       print_headers(req);
	  
	  ci_debug_printf(2, "Done\n");
     }
     close(conn->fd);      
     return 0;
}
예제 #14
0
void child_main(int sockfd, int pipefd)
{
     ci_thread_t thread;
     int i, ret;

     signal(SIGTERM, SIG_IGN);  /*Ignore parent requests to kill us untill we are up and running */
     ci_thread_mutex_init(&threads_list_mtx);
     ci_thread_mutex_init(&counters_mtx);
     ci_thread_cond_init(&free_server_cond);
     
     ci_stat_attach_mem(child_data->stats, child_data->stats_size, NULL);

     threads_list =
         (server_decl_t **) malloc((CI_CONF.THREADS_PER_CHILD + 1) *
                                   sizeof(server_decl_t *));
     con_queue = init_queue(CI_CONF.THREADS_PER_CHILD);

     for (i = 0; i < CI_CONF.THREADS_PER_CHILD; i++) {
          if ((threads_list[i] = newthread(con_queue)) == NULL) {
               exit(-1);        // FATAL error.....
          }
          ret =
              ci_thread_create(&thread, (void *(*)(void *)) thread_main,
                               (void *) threads_list[i]);
          threads_list[i]->srv_pthread = thread;
     }
     threads_list[CI_CONF.THREADS_PER_CHILD] = NULL;
     /*Now start the listener thread.... */
     ret = ci_thread_create(&thread, (void *(*)(void *)) listener_thread,
                            (void *) &sockfd);
     listener_thread_id = thread;
     
     /*set srand for child......*/
     srand(((unsigned int)time(NULL)) + (unsigned int)getpid());
     /*I suppose that all my threads are up now. We can setup our signal handlers */
     child_signals();

     /* A signal from parent may comes while we are starting.
        Listener will not accept any request in this case, (it checks on 
        the beggining of the accept loop for parent commands) so we can 
        shutdown imediatelly even if the parent said gracefuly.*/
     if (child_data->father_said)
         child_data->to_be_killed = IMMEDIATELY;

     /*start child commands may have non thread safe code but the worker threads
       does not serving requests yet.*/
     commands_execute_start_child();

     /*Signal listener to start accepting requests.*/
     int doStart = 0;
     do {
         ci_thread_mutex_lock(&counters_mtx);
         doStart = listener_running;
         ci_thread_mutex_unlock(&counters_mtx);
         if (!doStart)
             ci_usleep(5);
     } while(!doStart);
     ci_thread_cond_signal(&free_server_cond);

     while (!child_data->to_be_killed) {
          char buf[512];
          int bytes;
          if ((ret = ci_wait_for_data(pipefd, 1, wait_for_read)) > 0) { /*data input */
               bytes = ci_read_nonblock(pipefd, buf, 511);
               if (bytes == 0) {
                    ci_debug_printf(1,
                                    "Parent closed the pipe connection! Going to term immediately!\n");
                    child_data->to_be_killed = IMMEDIATELY;
               } else {
                    buf[bytes] = '\0';
                    handle_child_process_commands(buf);
               }
          }
          else if (ret < 0) {
               ci_debug_printf(1,
                               "An error occured while waiting for commands from parent. Terminating!\n");
               child_data->to_be_killed = IMMEDIATELY;
          }
          if (!listener_running && !child_data->to_be_killed) {
               ci_debug_printf(1,
                               "Ohh!! something happened to listener thread! Terminating\n");
               child_data->to_be_killed = GRACEFULLY;
          }
          commands_exec_scheduled();
     }

     ci_debug_printf(5, "Child :%d going down :%s\n", getpid(),
                     child_data->to_be_killed == IMMEDIATELY? 
                     "IMMEDIATELY" : "GRACEFULLY");
     
     cancel_all_threads();
     commands_execute_stop_child();
     exit_normaly();
}
예제 #15
0
void *ldap_table_search(struct ci_lookup_table *table, void *key, void ***vals)
{
    struct ldap_table_data *data = (struct ldap_table_data *)table->data;
    LDAPMessage *msg, *entry;
    BerElement *aber;
    LDAP *ld;
    struct berval **attrs;
    void *return_value=NULL;
    char *attrname;
    int ret = 0, failures, i;
    ci_str_vector_t  *vect = NULL;
    size_t v_size;
    char filter[MAX_LDAP_FILTER_SIZE];
    char buf[2048];

    *vals = NULL;
    failures = 0;
    return_value = NULL;

    if(data->cache && ci_cache_search(data->cache, key, (void **)&vect, NULL, &ci_cache_read_vector_val)) {
        ci_debug_printf(4, "Retrieving from cache....\n");
        if (!vect) /*Negative hit*/
            return NULL;
        *vals = (void **)ci_vector_cast_to_voidvoid(vect);
        return key;
    }

    create_filter(filter, MAX_LDAP_FILTER_SIZE, data->filter,key);

    while ((ld = ldap_connection_open(data->pool)) && failures < 5) {

        ret = ldap_search_ext_s(ld,
                                data->base, /*base*/
                                LDAP_SCOPE_SUBTREE, /*scope*/
                                filter, /*filter*/
                                data->attrs,  /*attrs*/
                                0,    /*attrsonly*/
                                NULL, /*serverctrls*/
                                NULL, /*clientctrls*/
                                NULL, /*timeout*/
                                -1,   /*sizelimit*/
                                &msg /*res*/
                               );

        ci_debug_printf(4, "Contacting LDAP server: %s\n", ldap_err2string(ret));
        if(ret == LDAP_SUCCESS) {
            entry = ldap_first_entry(ld, msg);
            while(entry != NULL) {
                aber = NULL;
                attrname = ldap_first_attribute(ld, entry, &aber);
                while(attrname != NULL) {
                    if (vect == NULL) {
                        vect = ci_str_vector_create(MAX_DATA_SIZE);
                        if (!vect)
                            return NULL;
                    }

                    ci_debug_printf(8, "Retrieve attribute:%s. Values: ", attrname);
                    attrs = ldap_get_values_len(ld, entry, attrname);
                    for(i = 0; attrs[i] != NULL ; ++i) {
                        //OpenLdap nowhere documents that the result is NULL terminated.
                        // copy to an intermediate buffer and terminate it before store to vector
                        v_size = sizeof(buf) <= attrs[i]->bv_len + 1 ? sizeof(buf) : attrs[i]->bv_len;
                        memcpy(buf, attrs[i]->bv_val, v_size);
                        buf[v_size] = '\0';
                        (void)ci_str_vector_add(vect, buf);
                        ci_debug_printf(8, "%s,", buf);
                    }
                    ci_debug_printf(8, "\n");
                    ldap_value_free_len(attrs);
                    attrname = ldap_next_attribute(ld, entry, aber);
                }
                if(aber)
                    ber_free(aber, 0);

                if(!return_value)
                    return_value = key;

                entry = ldap_next_entry(ld, entry);
            }
            ldap_msgfree(msg);
            ldap_connection_release(data->pool, ld, 0);

            if(data->cache) {
                v_size =  vect != NULL ? ci_cache_store_vector_size(vect) : 0;
                ci_debug_printf(4, "adding to cache\n");
                if (!ci_cache_update(data->cache, key, vect, v_size, ci_cache_store_vector_val))
                    ci_debug_printf(4, "adding to cache failed!\n");
            }

            if (!vect)
                return NULL;

            *vals = (void **)ci_vector_cast_to_voidvoid(vect);
            return return_value;
        }

        ldap_connection_release(data->pool, ld, 1);

        if (ret != LDAP_SERVER_DOWN) {
            ci_debug_printf(1, "Error contacting LDAP server: %s\n", ldap_err2string(ret));
            return NULL;
        }

        failures++;
    }

    ci_debug_printf(1, "Error LDAP server is down: %s\n", ldap_err2string(ret));
    return NULL;
}
예제 #16
0
int cfg_default_acl_access(char *directive, char **argv, void *setdata)
{
     int type, argc, error=0;
     int only_connection =0;
     char *acl_spec_name;
     ci_access_entry_t **tolist,*access_entry;
     const ci_acl_spec_t *acl_spec;
     const ci_acl_type_t *spec_type ;

     if (argv[0] == NULL || argv[1] == NULL) {
          ci_debug_printf(1, "Parse error in directive %s \n", directive);
          return 0;
     }

     if (strcmp("client_access", directive)==0) {
	 tolist = &acl_connection_access_list;
	 only_connection = 1;
     }
     else if(strcmp("icap_access", directive)==0) {
	 tolist = &acl_access_list;
     }
     else
	 return 0;

     if (strcmp(argv[0], "allow") == 0) {
          type = CI_ACCESS_ALLOW;

     }
     else if (strcmp(argv[0], "deny") == 0) {
          type = CI_ACCESS_DENY;
     }
     else {
          ci_debug_printf(1, "Invalid directive :%s. Disabling %s acl rule \n",
                          argv[0], argv[1]);
          return 0;
     }
     
     if ((access_entry = ci_access_entry_new(tolist, type)) == NULL) {
	 ci_debug_printf(1,"Error creating new access entry as %s access list\n", argv[0]);
	 return 0;
     }

     ci_debug_printf(2,"Creating new access entry as %s with specs:\n", argv[0]);
     for(argc=1; argv[argc] != NULL; argc++){	  
	  acl_spec_name = argv[argc];
          acl_spec = ci_acl_search(acl_spec_name);
          if (acl_spec)
              spec_type = acl_spec->type;
          else
              spec_type = NULL;
	  if(only_connection && spec_type && 
	     strcmp(spec_type->name,"port") != 0 && 
	     strcmp(spec_type->name,"src") != 0 &&
	     strcmp(spec_type->name,"srvip") != 0 ) 
	  {
	       ci_debug_printf(1, "Only \"port\", \"src\" and \"srvip\" acl types allowed in client_access access list (given :%s)\n", acl_spec_name);
	       error = 1;
	  }
	  else {
	       /*TODO: check return type.....*/
	       ci_access_entry_add_acl_by_name(access_entry, acl_spec_name);
	       ci_debug_printf(2,"\tAdding acl spec: %s\n", acl_spec_name);
	  }
     }
     if(error)
	  return 0;
     else
	  return 1;
}
예제 #17
0
int ci_client_icapfilter(ci_request_t * req,
                         int timeout,
                         ci_headers_list_t * headers,
                         void *data_source, int (*source_read) (void *, char *,
                                                                int),
                         void *data_dest, int (*dest_write) (void *, char *,
                                                             int))
{
     int i, ret, v1, v2, remains, pre_eof = 0, preview_status;
     char *buf, *val;

     if (CI_OK !=
         client_create_request(req, req->req_server, req->service,
                               req->type)) {
          ci_debug_printf(1, "Error making respmod request ....\n");
          return CI_ERROR;
     }

     if (!data_source)
       req->preview = -1;

     if (req->preview > 0) {    /*The preview data will be send with headers.... */
          ci_buf_mem_alloc(&(req->preview_data), req->preview); /*Alloc mem for preview data */
          buf = req->preview_data.buf;
          remains = req->preview;
          while (remains && !pre_eof) { /*Getting the preview data */
               if ((ret = (*source_read) (data_source, buf, remains)) <= 0) {
                    pre_eof = 1;
                    break;
               }
               remains -= ret;

          }
          req->preview -= remains;
          req->preview_data.used = req->preview;
     }
     if (pre_eof)
          req->eof_received = 1;

     /*Add the user supplied headers */
     if (req->type == ICAP_REQMOD && headers) {
          ci_http_request_create(req, (data_source!= NULL));
          for (i = 0; i < headers->used; i++) {
               ci_http_request_add_header(req, headers->headers[i]);
          }
     }
     else if (headers) {
          ci_http_response_create(req, 1, 1);
          for (i = 0; i < headers->used; i++) {
               ci_http_response_add_header(req, headers->headers[i]);
          }
     }
     else
          ci_http_response_create(req, 0, 1);

     if ((ret = client_send_request_headers(req, pre_eof, timeout)) < 0) {
          return CI_ERROR;
     }

     /*send body */

     /* ci_headers_reset(req->head);*/
     for (i = 0; req->entities[i] != NULL; i++) {
          ci_request_release_entity(req, i);
     }
     preview_status = 100;

     if (req->preview >= 0) {   /*we must wait for ICAP responce here..... */

          do {
               ci_wait_for_incomming_data(req->connection->fd, timeout);
               if (net_data_read(req) == CI_ERROR)
                    return CI_ERROR;
          } while (client_parse_icap_header(req, req->response_header) == CI_NEEDS_MORE);

          sscanf(req->response_header->buf, "ICAP/%d.%d %d", &v1, &v2, &preview_status);
          ci_debug_printf(3, "Preview response was with status: %d \n",
                          preview_status);
          if (req->eof_received && preview_status == 200) {
               ci_headers_unpack(req->response_header);
               if ((val = ci_headers_search(req->response_header, "Encapsulated")) == NULL) {
                    ci_debug_printf(1, "No encapsulated entities!\n");
                    return CI_ERROR;
               }
               process_encapsulated(req, val);
               if (!req->entities[1])   /*Then we have only body */
                    req->status = GET_BODY;
               else
                    req->status = GET_HEADERS;
          }
          else
	       ci_headers_reset(req->response_header);
     }

     if (preview_status == 204)
          return 204;

     ret =
         client_send_get_data(req, timeout, data_source, source_read, data_dest,
                              dest_write);
     return ret;
}
예제 #18
0
int ci_regex_apply(const ci_regex_t regex, const char *str, int len, int recurs, ci_list_t *matches, const void *user_data)
{
    int count = 0, i;
    ci_regex_replace_part_t parts;

    if (!str)
        return 0;

#ifdef HAVE_PCRE
    int ovector[OVECCOUNT];
    int rc;
    int offset = 0;
    int str_length = len >=0 ? len : strlen(str);
    do {
        memset(ovector, 0, sizeof(ovector));
        rc = pcre_exec(regex, NULL, str, str_length, offset, 0, ovector, OVECCOUNT);
        if (rc >= 0 && ovector[0] != ovector[1]) {
            ++count;
            ci_debug_printf(9, "Match pattern (pos:%d-%d): '%.*s'\n",
                            ovector[0], ovector[1], ovector[1]-ovector[0], str+ovector[0]);
            offset = ovector[1];
            if (matches) {
                parts.user_data = user_data;
                memset(parts.matches, 0 , sizeof(ci_regex_matches_t));
                for (i = 0; i < 10 && ovector[2*i+1] > ovector[2*i]; ++i) {
                    ci_debug_printf(9, "\t sub-match pattern (pos:%d-%d): '%.*s'\n", ovector[2*i], ovector[2*i+1], ovector[2*i + 1] - ovector[2*i], str+ovector[2*i]);
                    parts.matches[i].s = ovector[2*i];
                    parts.matches[i].e = ovector[2*i+1];
                }
                ci_list_push_back(matches, (void *)&parts);
            }
        }
    } while (recurs && rc >=0  && offset < str_length);

#else
    int retcode;
    regmatch_t pmatch[10];
    do {
        if ((retcode = regexec(regex, str, 10, pmatch, 0)) == 0) {
            ++count;
            ci_debug_printf(9, "Match pattern (pos:%d-%d): '%.*s'\n", pmatch[0].rm_so, pmatch[0].rm_eo, pmatch[0].rm_eo - pmatch[0].rm_so, str+pmatch[0].rm_so);

               if (matches) {
                   parts.user_data = user_data;
                   memset(parts.matches, 0, sizeof(ci_regex_matches_t));
                   for (i = 0; i < 10 && pmatch[i].rm_eo > pmatch[i].rm_so; ++i) {
                       ci_debug_printf(9, "\t sub-match pattern (pos:%d-%d): '%.*s'\n", pmatch[i].rm_so, pmatch[i].rm_eo, pmatch[i].rm_eo - pmatch[i].rm_so, str+pmatch[i].rm_so);
                       parts.matches[i].s = pmatch[i].rm_so;
                       parts.matches[i].e = pmatch[i].rm_eo;
                   }
                   ci_list_push_back(matches, (void *)&parts);
               }

            if (pmatch[0].rm_so >= 0 && pmatch[0].rm_eo >= 0 && pmatch[0].rm_so != pmatch[0].rm_eo) {
                str += pmatch[0].rm_eo;
                ci_debug_printf(8, "I will check again starting from: %s\n", str);
            } else /*stop here*/
                str = NULL;
        }
    } while (recurs && str && *str != '\0' && retcode == 0);
#endif

    ci_debug_printf(5, "ci_regex_apply matches count: %d\n", count);
    return count;
}
예제 #19
0
int client_parse_incoming_data(ci_request_t * req, void *data_dest,
                               int (*dest_write) (void *, char *, int))
{
     int ret, v1, v2, status, bytes, size;
     char *buf, *val;
     ci_headers_list_t *resp_heads;

     if (req->status == GET_NOTHING) {
          /*And reading the new ..... */
          ret = client_parse_icap_header(req, req->response_header);
          if (ret != CI_OK)
               return ret;
          sscanf(req->response_header->buf, "ICAP/%d.%d %d", &v1, &v2, &status);
          ci_debug_printf(3, "Response was with status:%d \n", status);
          ci_headers_unpack(req->response_header);

          if (ci_allow204(req) && status == 204) {
	       req->status = GET_EOF;
               return 204;
	  }

          if ((val = ci_headers_search(req->response_header, "Encapsulated")) == NULL) {
               ci_debug_printf(1, "No encapsulated entities!\n");
               return CI_ERROR;
          }
          process_encapsulated(req, val);

          if (!req->entities[0])
               return CI_ERROR;

          if (!req->entities[1]) {      /*Then we have only body */
               req->status = GET_BODY;
               if (req->pstrblock_read_len == 0)
                    return CI_NEEDS_MORE;
          }
          else {
               req->status = GET_HEADERS;
               size = req->entities[1]->start - req->entities[0]->start;
               resp_heads = req->entities[0]->entity;
               if (!ci_headers_setsize(resp_heads, size))
                    return CI_ERROR;
          }

//        return CI_NEEDS_MORE;
     }

     /*read encups headers */

     /*Non option responce has one or two entities: 
        "req-headers req-body|null-body" or [resp-headers] resp-body||null-body   
        So here client_parse_encaps_header will be called for one headers block
      */

     if (req->status == GET_HEADERS) {
          size = req->entities[1]->start - req->entities[0]->start;
          resp_heads = req->entities[0]->entity;
          if ((ret =
               client_parse_encaps_header(req, resp_heads, size)) != CI_OK)
               return ret;


          ci_headers_unpack(resp_heads);
          ci_debug_printf(5, "OK reading headers, going to read body\n");

          /*reseting body chunks related variables */
          req->current_chunk_len = 0;
          req->chunk_bytes_read = 0;
          req->write_to_module_pending = 0;

	  if (req->entities[1]->type == ICAP_NULL_BODY) {
	       req->status = GET_EOF;
	       return CI_OK;
	  }
	  else {
	       req->status = GET_BODY;
	       if (req->pstrblock_read_len == 0)
	            return CI_NEEDS_MORE;
	  }
     }

     if (req->status == GET_BODY) {
          do {
               if ((ret = parse_chunk_data(req, &buf)) == CI_ERROR) {
                    ci_debug_printf(1,
                                    "Error parsing chunks, current chunk len: %d, read: %d, readlen: %d, str: %s\n",
                                    req->current_chunk_len,
                                    req->chunk_bytes_read,
                                    req->pstrblock_read_len,
                                    req->pstrblock_read);
                    return CI_ERROR;
               }

               while (req->write_to_module_pending > 0) {
                    bytes =
                        (*dest_write) (data_dest, buf,
                                       req->write_to_module_pending);
                    if (bytes < 0) {
                         ci_debug_printf(1, "Error writing to output file!\n");
                         return CI_ERROR;
                    }
                    req->write_to_module_pending -= bytes;
               }

               if (ret == CI_EOF) {
                    req->status = GET_EOF;
                    return CI_OK;
               }
          } while (ret != CI_NEEDS_MORE);

          return CI_NEEDS_MORE;
     }

     return CI_OK;
}
예제 #20
0
파일: decode.c 프로젝트: p1rate5s/c-icap
/*return:
  1 on success
  -1 on error
  0 if max_size reached.
 */
int virus_scan_inflate(int fin, ci_simple_file_t *fout, ci_off_t max_size) {
    int ret, retriable;
    unsigned have, written;
    ci_off_t insize, outsize;
    z_stream strm;
    unsigned char in[CHUNK];
    unsigned char out[CHUNK];

    /* allocate inflate state */
    strm.zalloc = alloc_a_buffer;
    strm.zfree = free_a_buffer;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit2(&strm, 32 + 15);
    if (ret != Z_OK)
        return INFL_ERR_ERROR;

    retriable = 1;
    outsize = 0;
    insize = 0;
    /* decompress until deflate stream ends or end of file */
    do {
        strm.avail_in = do_file_read(fin, in, CHUNK);
        if (strm.avail_in < 0) {
            (void)inflateEnd(&strm);
            return INFL_ERR_ERROR;
        }
        if (strm.avail_in == 0) {
            break;
        }
        strm.next_in = in;
        insize += strm.avail_in;

        /* run inflate() on input until output buffer not full */
        do {
virus_scan_inflate_retry:
            strm.avail_out = CHUNK;
            strm.next_out = out;
            ret = inflate(&strm, Z_NO_FLUSH);
            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
            switch (ret) {
            case Z_NEED_DICT:
            case Z_DATA_ERROR:
                if (retriable) {
                    ret = inflateInit2(&strm, -15);
                    retriable = 0;
                    if (ret == Z_OK) {
                       strm.avail_in = insize;
                       strm.next_in = in;
                       goto virus_scan_inflate_retry;
                    }
                    /*else let fail ...*/
                }
            case Z_MEM_ERROR:
                inflateEnd(&strm);
                return INFL_ERR_CORRUPT;
            }
            retriable = 0; // No more retries allowed
            have = CHUNK - strm.avail_out;
            if ((written = do_file_write(fout, out, have)) != have) {
                inflateEnd(&strm);
                return INFL_ERR_OUTPUT;
            }
            outsize += written;
            if (max_size > 0 && outsize > max_size) {
                inflateEnd(&strm);
                if ( (outsize/insize) > 100) {
                    ci_debug_printf(1, "Compression ratio UncompSize/CompSize = %" PRINTF_OFF_T "/%" PRINTF_OFF_T " = %" PRINTF_OFF_T "! Is it a zip bomb? aborting!\n", (CAST_OFF_T)outsize, (CAST_OFF_T)insize, (CAST_OFF_T)(outsize/insize));
                    return INFL_ERR_BOMB;  /*Probably compression bomb object*/
                }
                else {
                    ci_debug_printf(4, "Object is bigger than max scannable file\n");
                    return INFL_ERR_NONE;
                }
            }
        } while (strm.avail_out == 0);

        /* done when inflate() says it's done */
    } while (ret != Z_STREAM_END);

    ci_simple_file_write(fout, NULL, 0, 1);
    /* clean up and return */
    inflateEnd(&strm);
    return ret == Z_STREAM_END ? INFL_OK : INFL_ERR_CORRUPT;
}
예제 #21
0
int worker_main(ci_socket sockfd)
{
     ci_connection_t conn;
     int claddrlen = sizeof(struct sockaddr_in);
//     char clientname[300];
     int haschild = 1, jobs_in_queue = 0;
     int pid = 0, error;


     for (;;) {                 //Global for
          if (!ci_proc_mutex_lock(&accept_mutex)) {
               if (child_data->to_be_killed)
                    return 1;
               continue;
          }
          child_data->idle = 0;
          pid = (int) child_data->pid;
          ci_debug_printf(1, "Child %d getting requests now ...\n", pid);

          do {                  //Getting requests while we have free servers.....
               ci_debug_printf(1, "In accept loop..................\n");
               error = 0;
               if (((conn.fd =
                     accept(sockfd, (struct sockaddr *) &(conn.claddr.sockaddr),
                            &claddrlen)) == INVALID_SOCKET) &&
//             if(((conn.fd = WSAAccept(sockfd, (struct sockaddr *)&(conn.claddr), &claddrlen,NULL,NULL)) == INVALID_SOCKET ) && 
                   (error = WSAGetLastError())) {
                    ci_debug_printf(1,
                                    "error accept .... %d\nExiting server ....\n",
                                    error);
                    exit(-1);   //For the moment .......
               }

               ci_debug_printf(1, "Accepting one connection...\n");
               claddrlen = sizeof(conn.srvaddr.sockaddr);
               getsockname(conn.fd,
                           (struct sockaddr *) &(conn.srvaddr.sockaddr),
                           &claddrlen);

               ci_fill_sockaddr(&conn.claddr);
               ci_fill_sockaddr(&conn.srvaddr);

               icap_socket_opts(sockfd, MAX_SECS_TO_LINGER);

               if ((jobs_in_queue = put_to_queue(con_queue, &conn)) == 0) {
                    ci_debug_printf(1,
                                    "ERROR!!!!!!NO AVAILABLE SERVERS!!!!!!!!!\n");
//                  child_data->to_be_killed=GRACEFULLY;
                    ci_debug_printf(1,
                                    "Jobs in Queue: %d, Free servers: %d, Used Servers: %d, Requests: %d\n",
                                    jobs_in_queue, child_data->freeservers,
                                    child_data->usedservers,
                                    child_data->requests);
               }
               ci_thread_mutex_lock(&counters_mtx);
               haschild = (child_data->freeservers ? 1 : 0);
               ci_thread_mutex_unlock(&counters_mtx);
               (child_data->connections)++;     //NUM of Requests....
          } while (haschild);

          child_data->idle = 1;
          ci_proc_mutex_unlock(&accept_mutex);

          ci_thread_mutex_lock(&counters_mtx);
          if (child_data->freeservers == 0) {
               ci_debug_printf(1,
                               "Child %d waiting for a thread to accept more connections ...\n",
                               pid);
               ci_thread_cond_wait(&free_server_cond, &counters_mtx);
          }
          ci_thread_mutex_unlock(&counters_mtx);

     }

}
예제 #22
0
int main(int argc, char **argv)
{
     int fd_in = 0, fd_out = 0;
     int ret;
     char ip[CI_IPLEN];
     ci_connection_t *conn;
     ci_request_t *req;
     ci_headers_list_t *req_headers = NULL;
     ci_headers_list_t *resp_headers = NULL;

     CI_DEBUG_LEVEL = 1;        /*Default debug level is 1 */
     ci_cfg_lib_init();

     if (!ci_args_apply(argc, argv, options)) {
          ci_args_usage(argv[0], options);
          exit(-1);
     }

#if ! defined(_WIN32)
     __log_error = (void (*)(void *, const char *,...)) log_errors;     /*set c-icap library log  function */
#else
     __vlog_error = vlog_errors;        /*set c-icap library  log function for win32..... */
#endif


     if (!(conn = ci_client_connect_to(icap_server, port, 0))) {
          ci_debug_printf(1, "Failed to connect to icap server.....\n");
          exit(-1);
     }

     req = ci_client_request(conn, icap_server, service);

     if (xheaders)
	 ci_icap_append_xheaders(req, xheaders);

     ci_client_get_server_options(req, CONN_TIMEOUT);
     ci_debug_printf(10, "OK done with options!\n");
     ci_conn_remote_ip(conn, ip);
     ci_debug_printf(1, "ICAP server:%s, ip:%s, port:%d\n\n", icap_server, ip,
                     port);

     if (!send_preview) {
         req->preview = -1;
     } else if (preview_size >= 0 && preview_size < req->preview) {
         req->preview = preview_size;
     }

     /*If service does not support allow 204 disable it*/
     if (!req->allow204)
         allow204 = 0;
     
     if (!input_file && !request_url && !resp_url) {
          ci_debug_printf(1, "OPTIONS:\n");
          ci_debug_printf(1,
                          "\tAllow 204: %s\n\tPreview: %d\n\tKeep alive: %s\n",
                          (req->allow204 ? "Yes" : "No"), req->preview,
                          (req->keepalive ? "Yes" : "No")
              );
          print_headers(req);
     }
     else {
          if (input_file && (fd_in = open(input_file, O_RDONLY)) < 0) {
               ci_debug_printf(1, "Error opening file %s\n", input_file);
               exit(-1);
          }

          if (output_file) {
               if ((fd_out =
                    open(output_file, O_CREAT | O_RDWR | O_EXCL,
                         S_IRWXU | S_IRGRP)) < 0) {
                    ci_debug_printf(1, "Error opening output file %s\n",
                                    output_file);
                    exit(-1);
               }
          }
          else {
               fd_out = fileno(stdout);
          }

          ci_client_request_reuse(req);

          ci_debug_printf(10, "Preview:%d keepalive:%d,allow204:%d\n",
                          req->preview, req->keepalive, req->allow204);

          ci_debug_printf(10, "OK allocating request going to send request\n");

	  req->type = ICAP_RESPMOD;
          if (allow204)
              req->allow204 = 1;
          if (allow206)
              req->allow206 = 1;

	  if (xheaders)
	      ci_icap_append_xheaders(req, xheaders);

	  if (request_url) {
	       req_headers = ci_headers_create();
               build_reqmod_headers(request_url, method_str, fd_in, req_headers);
	       req->type = ICAP_REQMOD;
	  }
          else if (send_headers) {
               resp_headers = ci_headers_create();
	       build_respmod_headers(fd_in, resp_headers);
               if (resp_url) {
                   req_headers = ci_headers_create();
	           build_reqmod_headers(resp_url, method_str, 0, req_headers);
               }
          }

	  if(req_headers && http_xheaders)
	      ci_headers_addheaders(req_headers, http_xheaders);

          if (resp_headers && http_resp_xheaders)
	      ci_headers_addheaders(resp_headers, http_resp_xheaders);

          ret = ci_client_icapfilter(req,
                                     CONN_TIMEOUT,
                                     req_headers,
                                     resp_headers,
                                     (fd_in > 0 ? (&fd_in): NULL),
                                     (int (*)(void *, char *, int)) fileread,
                                     &fd_out,
                                     (int (*)(void *, char *, int)) filewrite);

          if (ret == 206) {
              ci_debug_printf(1, "Partial modification (Allow 206 response): "
                              "use %ld from the original body data\n", 
                              req->i206_use_original_body);
              copy_data(fd_in, fd_out, req->i206_use_original_body);

          }

          close(fd_in);
          close(fd_out);

          if (ret == 204) {
               ci_debug_printf(1,
                               "No modification needed (Allow 204 response)\n");
               if (output_file)
                    unlink(output_file);
          }

          if (verbose)
               print_headers(req);

          ci_debug_printf(2, "Done\n");
     }
     ci_connection_destroy(conn);
     return 0;
}
예제 #23
0
int send_handles(DWORD child_ID,
                 HANDLE pipe,
                 HANDLE child_handle,
                 SOCKET sock_fd,
                 HANDLE accept_mtx,
                 HANDLE shmem_id, HANDLE shmem_mtx, int qsize)
{
     DWORD dwWritten;
     HANDLE dupmutex;
     HANDLE dupshmem, dupshmemmtx;
     WSAPROTOCOL_INFO sock_info;

     memset(&sock_info, 0, sizeof(sock_info));

     if (WSADuplicateSocket(sock_fd, child_ID, &sock_info) != 0) {
          ci_debug_printf(1, "Error socket duplicating:%d\n",
                          WSAGetLastError());
     }

     DuplicateHandle(GetCurrentProcess(),
                     accept_mtx,
                     child_handle, &dupmutex, SYNCHRONIZE, FALSE, 0);
     DuplicateHandle(GetCurrentProcess(),
                     shmem_id,
                     child_handle,
                     &dupshmem, SYNCHRONIZE, FALSE, DUPLICATE_SAME_ACCESS);

     DuplicateHandle(GetCurrentProcess(),
                     shmem_mtx,
                     child_handle,
                     &dupshmemmtx, SYNCHRONIZE, FALSE, DUPLICATE_SAME_ACCESS);

     if (!WriteFile(pipe, &child_handle, sizeof(HANDLE), &dwWritten, NULL) ||
         dwWritten != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error sending handles\n");
          return 0;
     }

     if (!WriteFile(pipe, &pipe, sizeof(HANDLE), &dwWritten, NULL) ||
         dwWritten != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error sending handles\n");
          return 0;
     }

     if (!WriteFile(pipe, &dupmutex, sizeof(HANDLE), &dwWritten, NULL) ||
         dwWritten != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error sending handles\n");
          return 0;
     }
     if (!WriteFile(pipe, &dupshmem, sizeof(HANDLE), &dwWritten, NULL) ||
         dwWritten != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error sending handles\n");
          return 0;
     }
     if (!WriteFile(pipe, &dupshmemmtx, sizeof(HANDLE), &dwWritten, NULL) ||
         dwWritten != sizeof(HANDLE)) {
          ci_debug_printf(1, "Error sending handles\n");
          return 0;
     }
     if (!WriteFile(pipe, &qsize, sizeof(int), &dwWritten, NULL) ||
         dwWritten != sizeof(int)) {
          ci_debug_printf(1, "Error sending handles\n");
          return 0;
     }
     if (!WriteFile
         (pipe, &sock_info, sizeof(WSAPROTOCOL_INFO), &dwWritten, NULL)
         || dwWritten != sizeof(WSAPROTOCOL_INFO)) {
          ci_debug_printf(1, "Error sending handles\n");
          return 0;
     }
//   sprintf(buf,"%d:%d:%d:%d:%d",child_handle,dupmutex,dupshmem,dupshmemmtx,qsize);
//   WriteFile(pipe, buf, strlen(buf)+1, &dwWritten, NULL);
     return 1;
}
예제 #24
0
void info_close_service() 
{
     ci_debug_printf(5,"Service %s shutdown!\n", info_service.mod_name);
}
예제 #25
0
int start_server()
{

#ifdef MULTICHILD
     int child_indx, i;
     HANDLE child_handle;
     ci_thread_t mon_thread;
     int childs, freeservers, used, maxrequests;

     ci_proc_mutex_init(&accept_mutex);
     ci_thread_mutex_init(&control_process_mtx);

     if (!create_childs_queue(&childs_queue, MAX_CHILDS)) {
          log_server(NULL, "Can't init shared memory.Fatal error, exiting!\n");
          ci_debug_printf(1,
                          "Can't init shared memory.Fatal error, exiting!\n");
          exit(0);
     }

     for (i = 0; i < START_CHILDS + 2; i++) {
          child_handle = start_child(LISTEN_SOCKET);
     }

/*Start died childs monitor thread*/
/*     ci_thread_create(&mon_thread,
		      (void *(*)(void *))wait_achild_to_die,
		      (void *)NULL);
*/
     while (1) {
          if (check_for_died_child(5000))
               continue;
//        Sleep(5000); 
          childs_queue_stats(&childs_queue, &childs, &freeservers, &used,
                             &maxrequests);
          ci_debug_printf(1,
                          "Server stats: \n\t Childs:%d\n\t Free servers:%d\n\tUsed servers:%d\n\tRequests served:%d\n",
                          childs, freeservers, used, maxrequests);

          if ((freeservers <= MIN_FREE_SERVERS && childs < MAX_CHILDS)
              || childs < START_CHILDS) {
               ci_debug_printf(1, "Going to start a child .....\n");
               child_handle = start_child(LISTEN_SOCKET);
          }
          else if (freeservers >= MAX_FREE_SERVERS && childs > START_CHILDS) {
               ci_thread_mutex_lock(&control_process_mtx);
               if ((child_indx = find_an_idle_child(&childs_queue)) < 0)
                    continue;
               childs_queue.childs[child_indx].to_be_killed = GRACEFULLY;
               tell_child_to_die(childs_queue.childs[child_indx].pipe);
               ci_thread_mutex_unlock(&control_process_mtx);
               ci_debug_printf(1, "Going to stop child %d .....\n",
                               childs_queue.childs[child_indx].pid);
          }
     }
/*
     for(i=0;i<START_CHILDS;i++){
	  pid=wait(&status);
	  ci_debug_printf(1,"The child %d died with status %d\n",pid,status);
     }
*/


#else
     child_data = (child_shared_data_t *) malloc(sizeof(child_shared_data_t));
     child_data->pid = 0;
     child_data->freeservers = START_SERVERS;
     child_data->usedservers = 0;
     child_data->requests = 0;
     child_data->connections = 0;
     child_data->to_be_killed = 0;
     child_data->idle = 1;
     child_main(LISTEN_SOCKET);
#endif

     return 1;
}
예제 #26
0
LDAP *ldap_connection_open(struct ldap_connections_pool *pool)
{
    struct ldap_connection *conn;
    struct berval ldap_passwd, *servercred;
    int ret;
    char *ldap_user;
    if (ci_thread_mutex_lock(&pool->mutex)!=0)
        return NULL;
#ifdef LDAP_MAX_CONNECTIONS
    do {
#endif
        if (pool->inactive) {
            conn = pool->inactive;
            pool->inactive = pool->inactive->next;

            conn->next = pool->used;
            pool->used = conn;
            conn->hits++;
            ci_thread_mutex_unlock(&pool->mutex);
            return conn->ldap;
        }
#ifdef LDAP_MAX_CONNECTIONS
        if (pool->connections >= pool->max_connections) {
            /*wait for an ldap connection to be released. The condwait will unlock
              pool->mutex */
            if (ci_thread_cond_wait(&(pool->pool_cond), &(pool->mutex)) != 0) {
                ci_thread_mutex_unlock(&(pool->mutex));
                return NULL;
            }
        }
    } while(pool->connections >= pool->max_connections);
#else
        ci_thread_mutex_unlock(&pool->mutex);
#endif


    conn=malloc(sizeof(struct ldap_connection));
    if (!conn) {
#ifdef LDAP_MAX_CONNECTIONS
        ci_thread_mutex_unlock(&pool->mutex);
#endif
        return NULL;
    }
    conn->hits = 1;

    ret = ldap_initialize(&conn->ldap, pool->ldap_uri);
    if (!conn->ldap) {
#ifdef LDAP_MAX_CONNECTIONS
        ci_thread_mutex_unlock(&pool->mutex);
#endif
        ci_debug_printf(1, "Error allocating memory for ldap connection: %s!\n",
                        ldap_err2string(ret));
        free(conn);
        return NULL;
    }

    ldap_set_option(conn->ldap, LDAP_OPT_PROTOCOL_VERSION, &(pool->ldapversion));
    if (pool->user[0] != '\0')
        ldap_user = pool->user;
    else
        ldap_user = NULL;

    if (pool->password[0] != '\0') {
        ldap_passwd.bv_val = pool->password;
        ldap_passwd.bv_len = strlen(pool->password);
    }
    else {
        ldap_passwd.bv_val = NULL;
        ldap_passwd.bv_len = 0;
    }

    ret = ldap_sasl_bind_s( conn->ldap,
                            ldap_user,
                            LDAP_SASL_SIMPLE,
                            &ldap_passwd,
                            NULL,
                            NULL,
                            &servercred );

    if (ret != LDAP_SUCCESS) {
        ci_debug_printf(1, "Error bind to ldap server: %s!\n",ldap_err2string(ret));
#ifdef LDAP_MAX_CONNECTIONS
        ci_thread_mutex_unlock(&pool->mutex);
#endif
        ldap_unbind_ext_s(conn->ldap, NULL, NULL);
        free(conn);
        return NULL;
    }
    if(servercred) {
        ber_bvfree(servercred);
    }

#ifdef LDAP_MAX_CONNECTIONS
    /*we are already locked*/
#else
    if (ci_thread_mutex_lock(&pool->mutex)!= 0) {
        ci_debug_printf(1, "Error locking mutex while opening ldap connection!\n");
        ldap_unbind_ext_s(conn->ldap, NULL, NULL);
        free(conn);
        return NULL;
    }
#endif
    pool->connections++;
    conn->next = pool->used;
    pool->used = conn;
    ci_thread_mutex_unlock(&pool->mutex);
    return conn->ldap;
}
예제 #27
0
void *acl_time_dup(const char *str, ci_mem_allocator_t *allocator)
{
    struct {const char *day; int id;} days[] = {
        {"Sunday", 0}, {"Monday", 1}, {"Tuesday", 2}, {"Wednesday", 3},
        {"Thursday", 4}, {"Friday", 5}, {"Saturday", 6},
        {"S", 0}, {"M", 1}, {"T", 2}, {"W", 3}, {"H", 4}, {"F", 5}, {"A", 6},
        {NULL, -1}
    };
    int h1, m1, h2, m2, i;
    char *s, *e;
    const char *error;
    char buf[1024];
    struct acl_time_data *tmd = allocator->alloc(allocator, sizeof(struct acl_time_data));
    tmd->days = 0;
    /*copy string in order to parse it*/
    strncpy(buf, str, sizeof(buf));
    buf[sizeof(buf) - 1] = '\0';
    s = buf;
    if (!isdigit(*s)) {
        do {
            if (*s == ',') ++s;
            for (i = 0; days[i].day != NULL; ++i) {
                if (strncasecmp(s, days[i].day, strlen(days[i].day)) == 0) {
                    tmd->days |= 1 << days[i].id;
                    break;
                }
            }
            if (days[i].day == NULL) {
                /*not found*/
                error = s;
                goto acl_time_dup_fail;
            }
            s += strlen(days[i].day);

        } while(*s == ',');

        if (*s != '/') {
            error = s;
            goto acl_time_dup_fail;
        }
        if (*s) ++s;
    }

    /* Time region specification*/
    /*We are expecting hour region in the form 'HH:MM-HH:MM' */
    if (!isdigit(*s)) {
        error = s;
        goto acl_time_dup_fail;
    }

    h1 = strtol(s, &e, 10);
    if (h1 < 0 || h1 > 24) {
        error = s;
        goto acl_time_dup_fail;
    }
    if (*e != ':' || !isdigit(e[1])) {
        error = e;
        goto acl_time_dup_fail;
    }
    s = e + 1;
    m1 = strtol(s, &e, 10);
    if (m1 < 0 || m1 > 59) {
        error = s;
        goto acl_time_dup_fail;
    }
    if (*e != '-' || !isdigit(e[1])) {
        error = e;
        goto acl_time_dup_fail;
    }

    s = e + 1;
    h2 = strtol(s, &e, 10);
    if (h2 < 0 || h2 > 24) {
        error = s;
        goto acl_time_dup_fail;
    }
    if (*e != ':' || !isdigit(e[1])) {
        error = e;
        goto acl_time_dup_fail;
    }
    s = e + 1;
    m2 = strtol(s, &e, 10);
    if (m2 < 0 || m2 > 59) {
        error = s;
        goto acl_time_dup_fail;
    }
    tmd->start_time = h1 * 60 + m1;
    tmd->end_time = h2 * 60 + m2;

    if (tmd->start_time <= tmd->end_time) {
        ci_debug_printf(5, "Acl time, adding days: %x,  start time %d, end time: %d!\n", tmd->days, tmd->start_time, tmd->end_time);
        return tmd;
    }

    ci_debug_printf(1, "Acl '%s': end time is smaller than the start time!\n", str);
    error = str;

acl_time_dup_fail:
    ci_debug_printf(1, "Failed to parse acl time: %s (error on pos '...%s')\n", str, error);
    allocator->free(allocator, (void *)tmd);
    return NULL;
}
예제 #28
0
void *ldap_table_open(struct ci_lookup_table *table)
{
    int i;
    char *path;
    char tname[1024];
    struct ldap_table_data *ldapdata;
    ci_dyn_array_t *args = NULL;
    ci_array_item_t *arg = NULL;
    char *use_cache = "local";
    int cache_ttl = 60;
    size_t cache_size = 1*1024*1024;
    size_t cache_item_size = 2048;
    long int val;

    path = strdup(table->path);
    if (!path) {
        ci_debug_printf(1, "ldap_table_open: error allocating memory!\n");
        return NULL;
    }

    ldapdata = malloc(sizeof(struct ldap_table_data));
    if(!ldapdata) {
        free(path);
        ci_debug_printf(1, "ldap_table_open: error allocating memory (ldapdata)!\n");
        return NULL;
    }
    ldapdata->str = path;
    ldapdata->pool = NULL;
    ldapdata->base = NULL;
    ldapdata->server = NULL;
    ldapdata->port = 389;
    ldapdata->user = NULL;
    ldapdata->password = NULL;
    ldapdata->attrs = NULL;
    ldapdata->filter = NULL;
    ldapdata->name = NULL;

    if(!parse_ldap_str(ldapdata)) {
        free(ldapdata->str);
        free(ldapdata);
        ci_debug_printf(1, "ldap_table_open: parse path string error!\n");
        return NULL;
    }

    if (table->args) {
        if ((args = ci_parse_key_value_list(table->args, ','))) {
            for (i = 0; (arg = ci_dyn_array_get_item(args, i)) != NULL; ++i) {
                ci_debug_printf(5, "Table argument %s:%s\n", arg->name, (char *)arg->value);
                if(strcasecmp(arg->name, "name") == 0) {
                    ldapdata->name = strdup((char *)arg->value);
                } else if(strcasecmp(arg->name, "cache") == 0) {
                    if (strcasecmp((char *)arg->value, "no") == 0)
                        use_cache = NULL;
                    else
                        use_cache = (char *)arg->value;
                } else if (strcasecmp(arg->name, "cache-ttl") == 0) {
                    val = strtol((char *)arg->value, NULL, 10);
                    if (val > 0)
                        cache_ttl = val;
                    else
                        ci_debug_printf(1, "WARNING: wrong cache-ttl value: %ld, using default\n", val);
                } else if (strcasecmp(arg->name, "cache-size") == 0) {
                    val = ci_atol_ext((char *)arg->value, NULL);
                    if (val > 0)
                        cache_size = (size_t)val;
                    else
                        ci_debug_printf(1, "WARNING: wrong cache-size value: %ld, using default\n", val);
                } else if (strcasecmp(arg->name, "cache-item-size") == 0) {
                    val = ci_atol_ext((char *)arg->value, NULL);
                    if (val > 0)
                        cache_item_size = (size_t)val;
                    else
                        ci_debug_printf(1, "WARNING: wrong cache-item-size value: %ld, using default\n", val);
                }
            }
        }
    }

    ldapdata->pool = ldap_pool_create(ldapdata->server, ldapdata->port,
                                      ldapdata->user, ldapdata->password);
    if (use_cache) {
        snprintf(tname, sizeof(tname), "ldap:%s", ldapdata->name ? ldapdata->name : ldapdata->str);
        tname[sizeof(tname) - 1] = '\0';
        ldapdata->cache = ci_cache_build(tname, use_cache,
                                         cache_size, cache_item_size, cache_ttl,
                                         &ci_str_ops);
        if(!ldapdata->cache) {
            ci_debug_printf(1, "ldap_table_open: can not create cache! cache is disabled");
        }
    } else
        ldapdata->cache = NULL;

    table->data = ldapdata;

    /*Must released before exit, we have pointes pointing on args array items*/
    if (args)
        ci_dyn_array_destroy(args);
    return table->data;
}
예제 #29
0
int threadjobsendfiles()
{
     ci_request_t *req;
     ci_connection_t *conn;
     int port = 1344;
     int indx, keepalive, ret;
     int arand;

     while (1) {

	  if (!(conn = ci_client_connect_to(servername, port, AF_INET))) {
	    ci_debug_printf(1, "Failed to connect to icap server.....\n");
	    exit(-1);
	  }
	  req = ci_client_request(conn, servername, service);
          req->type = ICAP_RESPMOD;
	  req->preview = 512;

          for (;;) {


               ci_thread_mutex_lock(&filemtx);
               indx = file_indx;
               if (file_indx == (FILES_NUMBER - 1))
                    file_indx = 0;
               else
                    file_indx++;
               ci_thread_mutex_unlock(&filemtx);

               keepalive = 0;
               if ((ret = do_file(req, FILES[indx], &keepalive)) <= 0) {
		    ci_thread_mutex_lock(&statsmtx);
		    if (ret == 0) 
		         soft_failed_requests_stats++;
		    else 
		         failed_requests_stats++;
		    ci_thread_mutex_unlock(&statsmtx);
                    printf("Request failed...\n");
                    break;
               }

               ci_thread_mutex_lock(&statsmtx);
               requests_stats++;
               arand = rand();  /*rand is not thread safe .... */
               ci_thread_mutex_unlock(&statsmtx);

               if (_THE_END) {
                    printf("The end: thread dying\n");
		    ci_request_destroy(req);
                    return 0;
               }

	       if (keepalive == 0)
		 break;

               arand = (int) ((((double) arand) / (double) RAND_MAX) * 10.0);
               if (arand == 5 || arand == 7 || arand == 3) {    // 30% possibility ....
//                  printf("OK, closing the connection......\n");
                    break;
               }
//               sleep(1);
               usleep(500000);

//             printf("Keeping alive connection\n");

	       ci_client_request_reuse(req);
          }
	  ci_hard_close(conn->fd);
	  ci_request_destroy(req);
          usleep(1000000);
     }
}
예제 #30
0
int thread_main(server_decl_t * srv)
{
     ci_connection_t con;
     char clientname[CI_MAXHOSTNAMELEN + 1];
     int ret, request_status = CI_NO_STATUS;
     int keepalive_reqs;
//***********************
     thread_signals(0);
//*************************
     srv->srv_id = getpid();    //Setting my pid ...

     for (;;) {
          /*
             If we must shutdown IMEDIATELLY it is time to leave the server
             else if we are going to shutdown GRACEFULLY we are going to die 
             only if there are not any accepted connections
           */
          if (child_data->to_be_killed == IMMEDIATELY) {
               srv->running = 0;
               return 1;
          }

          if ((ret = get_from_queue(con_queue, &con)) == 0) {
               if (child_data->to_be_killed) {
                    srv->running = 0;
                    return 1;
               }
               ret = wait_for_queue(con_queue);
               continue;
          }

          if (ret < 0) {        //An error has occured
               ci_debug_printf(1,
                               "Fatal Error!!! Error getting a connection from connections queue!!!\n");
               break;
          }

          ci_thread_mutex_lock(&counters_mtx);  /*Update counters as soon as possible */
          (child_data->freeservers)--;
          (child_data->usedservers)++;
          ci_thread_mutex_unlock(&counters_mtx);

          ci_netio_init(con.fd);
          ret = 1;
          if (srv->current_req == NULL)
               srv->current_req = newrequest(&con);
          else
               ret = recycle_request(srv->current_req, &con);

          if (srv->current_req == NULL || ret == 0) {
               ci_sockaddr_t_to_host(&(con.claddr), clientname,
                                     CI_MAXHOSTNAMELEN);
               ci_debug_printf(1, "Request from %s denied...\n", clientname);
               hard_close_connection((&con));
               goto end_of_main_loop_thread;    /*The request rejected. Log an error and continue ... */
          }

          keepalive_reqs = 0;
          do {
               if (MAX_KEEPALIVE_REQUESTS > 0
                   && keepalive_reqs >= MAX_KEEPALIVE_REQUESTS)
                    srv->current_req->keepalive = 0;    /*do not keep alive connection */
               if (child_data->to_be_killed)    /*We are going to die do not keep-alive */
                    srv->current_req->keepalive = 0;

               if ((request_status = process_request(srv->current_req)) == CI_NO_STATUS) {
                    ci_debug_printf(5,
                                    "Process request timeout or interrupted....\n");
                    ci_request_reset(srv->current_req);
                    break;
               }
               srv->served_requests++;
               srv->served_requests_no_reallocation++;
               keepalive_reqs++;

               /*Increase served requests. I dont like this. The delay is small but I don't like... */
               ci_thread_mutex_lock(&counters_mtx);
               (child_data->requests)++;
               ci_thread_mutex_unlock(&counters_mtx);

               log_access(srv->current_req, request_status);
//             break; //No keep-alive ......

               if (child_data->to_be_killed  == IMMEDIATELY)
                    break;      //Just exiting the keep-alive loop

               /*if we are going to term gracefully we will try to keep our promice for
                 keepalived request....
                */
               if (child_data->to_be_killed  == GRACEFULLY && 
                   srv->current_req->keepalive == 0)
                    break;

               ci_debug_printf(8, "Keep-alive:%d\n",
                               srv->current_req->keepalive);
               if (srv->current_req->keepalive && keepalive_request(srv->current_req)) {
                   ci_debug_printf(8,
                                   "Server %d going to serve new request from client (keep-alive) \n",
                                   srv->srv_id);
               }
               else
                    break;
          } while (1);

          if (srv->current_req) {
               if (request_status != CI_OK || child_data->to_be_killed) {
                    hard_close_connection(srv->current_req->connection);
               }
               else {
                    close_connection(srv->current_req->connection);
               }
          }
          if (srv->served_requests_no_reallocation >
              MAX_REQUESTS_BEFORE_REALLOCATE_MEM) {
               ci_debug_printf(5,
                               "Max requests reached, reallocate memory and buffers .....\n");
               ci_request_destroy(srv->current_req);
               srv->current_req = NULL;
               srv->served_requests_no_reallocation = 0;
          }


        end_of_main_loop_thread:
          ci_thread_mutex_lock(&counters_mtx);
          (child_data->freeservers)++;
          (child_data->usedservers)--;
          ci_thread_mutex_unlock(&counters_mtx);
          ci_thread_cond_signal(&free_server_cond);

     }
     srv->running = 0;
     return 0;
}