Ejemplo n.º 1
0
extern "C" void delete_file (char *pathname, struct client client) {
  struct decafs_file_stat file_info;
  uint32_t num_chunks = 0, request_id = get_new_request_id();

  // If the file doesn't exist
  if ((decafs_file_sstat (pathname, &file_info, client)) < 0) {
    // TODO halli check if this change is correct
    // old call
    //if (send_delete_result (client, 0, FILE_NOT_FOUND) < 0) {
    if (send_remove_result (client, FILE_NOT_FOUND) < 0) {
      printf ("\tDelete result could not reach client.\n");
    }
    return;
  }

  if (get_exclusive_lock (client, file_info.file_id) < 0) {
    // TODO halli check if this change is correct
    // old call
    //if (send_delete_result (client, 0, FILE_IN_USE) < 0) {
    if (send_remove_result (client, FILE_IN_USE) < 0) {
      printf ("\tDelete result could not reach client.\n");
    }
    return;
  }

  // Save the request id.
  active_delete_requests[request_id] = request_info (client, file_info.file_id);
  printf ("(request: %d) processing delete file %s\n", request_id, pathname);
  num_chunks = process_delete_file (request_id, file_info.file_id);

  assert (delete_request_exists (request_id));
  active_delete_requests[request_id].chunks_expected = num_chunks;
  check_delete_complete(request_id);
}
Ejemplo n.º 2
0
int proxenet_start() 
{
	sock_t control_socket, listening_socket;
	struct sigaction saction;
	
	control_socket = listening_socket = -1;

	/* create control socket */
	control_socket = create_control_socket();
	if (control_socket < 0) {
		xlog(LOG_CRITICAL, "Cannot create control socket: %s\n", strerror(errno));
		return -1;
	}

#ifdef DEBUG
	xlog(LOG_INFO, "Control socket: %d\n", control_socket);
#endif
	
	/* create listening socket */
	listening_socket = create_bind_socket(cfg->iface, cfg->port);
	if (listening_socket < 0) {
		xlog(LOG_CRITICAL, "Cannot create bind socket: %s\n", strerror(errno));
		return -1;
	}

#ifdef DEBUG
	xlog(LOG_INFO, "Bind socket: %d\n", listening_socket);
#endif
	
	/* init everything */
	initialize_sigmask(&saction);

	plugins_list = NULL;
	proxy_state = INACTIVE;
	active_threads_bitmask = 0;
	
	/* set up plugins */
	if( proxenet_initialize_plugins_list() < 0 )
		return -1;
	
	proxenet_initialize_plugins(); // call *MUST* succeed or abort()

	/* setting request counter  */
	request_id = 0;
	get_new_request_id();
	
	/* prepare threads and start looping */
	xloop(listening_socket, control_socket);
	
	/* clean context */
	proxenet_remove_all_plugins();
	
	close_socket(listening_socket);
	close_socket(control_socket);

	unlink(CONTROL_SOCK_PATH);
	return 0;
}
Ejemplo n.º 3
0
extern "C" void node_up_handler_func (uint32_t node_number) {
  printf ("Handling node coming online...\n");
  auto itW = writeRequests.begin();
  while (itW!=writeRequests.end()) {
    if(itW->node_id == node_number) {
      uint32_t req_id = get_new_request_id();
      replace_request_lookups.insert(std::pair<uint32_t, uint32_t>(req_id, req_id));
      process_write_chunk (req_id, itW->fd, itW->file_id,
                                  itW->node_id, itW->stripe_id, itW->chunk_num,
                                   itW->offset, itW->buf, itW->count);

      printf("Write Request:\n file_id:%d \t node_id:%d\t stripe_id:%d\t chunk_num:%d\n",
        itW->file_id, itW->node_id, itW->stripe_id, itW->chunk_num);
      writeRequests.erase(itW);
      break;
    }
    itW++;
  }
  printf("finished restarting teh node :)\n");
}
Ejemplo n.º 4
0
extern "C" void write_file (int fd, const void *buf, size_t count, struct client client) {
  struct file_instance inst;
  struct decafs_file_stat stat;
  uint32_t stripe_id, num_chunks = 0, num_replica_chunks = 0;
  uint32_t chunks_written, replica_chunks_written;
  int file_offset, stripe_offset, bytes_written = 0, write_size = 0;
  uint32_t request_id = get_new_request_id();
  uint32_t replica_request_id = get_new_request_id();
  struct write_request request = {request_id, replica_request_id};

  assert (fd > 0);

  inst = get_file_info((uint32_t)fd);

  printf ("\n(BARISTA) Write request (%d bytes) from file %d\n",
             (int)count, (int)inst.file_id);

  // If the client does not have permission to write, return an error
  if (has_exclusive_lock (client, inst.file_id) <= 0) {
    if (send_write_result (client, 0, FILE_NOT_OPEN_FOR_WRITE) < 0) {
      printf ("\tWrite result could not reach client.\n");
    }
    return;
  }

  if (decafs_file_stat (inst.file_id, &stat, client) < 0) {
    if (send_write_result (client, 0, UNABLE_TO_STAT_FILE) < 0) {
      printf ("\tWrite result could not reach client.\n");
    }
    return;
  }

  if ((file_offset = get_file_cursor (fd)) < 0) {
    if (send_write_result (client, 0, FILE_NOT_OPEN_FOR_WRITE) < 0) {
      printf ("\tWrite result could not reach client.\n");
    }
    return;
  }

  // If we are requesting 0 bytes, return 0 bytes written
  if (count == 0) {
    if (send_write_result (client, 0, 0) < 0) {
      printf ("\tWrite result could not reach client.\n");
    }
    return;
  }

  // Save the request id
  write_request_lookups[request_id] = request;
  write_request_lookups[replica_request_id] = request;
  active_write_requests[request] = write_request_info (client, inst.file_id,
                                                       fd);

  // TODO: make some assertion about max write size here
  get_first_stripe (&stripe_id, &stripe_offset, stat.stripe_size, file_offset);

  while (bytes_written < (int)count) {
    if (count - bytes_written > stat.stripe_size - stripe_offset) {
      write_size = stat.stripe_size - stripe_offset;
    }
    else {
      write_size = count - bytes_written;
    }

    printf ("\t(request: (%d,%d)) sending stripe %d for processing (%d bytes)\n",
               request_id, replica_request_id, stripe_id, write_size);
    // TODO: add pathname here, get from persistent meta

    chunks_written = 0;
    replica_chunks_written = 0;

    process_write_stripe (request_id, replica_request_id,
                          &chunks_written, &replica_chunks_written,
                          inst.file_id, (char *)"", stripe_id,
                          stat.stripe_size, stat.chunk_size,
                          (uint8_t *)buf + bytes_written, stripe_offset,
                          write_size);

    num_chunks += chunks_written;
    num_replica_chunks += replica_chunks_written;

    // TODO (?): Move the file size update and cursor to check_write_complete()
    update_file_size (inst.file_id, write_size, client);
    set_file_cursor (fd, get_file_cursor (fd) + write_size, client);
    stripe_offset = 0;
    bytes_written += write_size;
    ++stripe_id;
  }
  assert (write_request_exists (request_id));
  active_write_requests[request].info.chunks_expected = num_chunks;
  active_write_requests[request].replica_info.chunks_expected =
                                              num_replica_chunks;
  check_write_complete(request_id);
}
Ejemplo n.º 5
0
extern "C" void read_file (int fd, size_t count, struct client client) {
  struct file_instance inst;
  struct decafs_file_stat stat;
  uint32_t stripe_id, num_chunks = 0;
  int file_offset, stripe_offset, bytes_read = 0, read_size = 0;
  uint8_t *buf;
  uint32_t request_id = get_new_request_id();

  assert (fd > 0);

  // Allocate space for the read request
  buf = (uint8_t *)malloc (count);

  inst = get_file_info((uint32_t)fd);

  printf ("\n(BARISTA) Read request (%d bytes)\n", (int)count);

  // If the client does not have permission to read, return an error
  if (has_exclusive_lock (client, inst.file_id) <= 0) {
    if (has_shared_lock (client, inst.file_id) <= 0) {
      if (send_read_result (client, 0, FILE_NOT_OPEN_FOR_READ, NULL) < 0) {
        printf ("\tRead result could not reach client.\n");
      }
      return;
    }
  }

  if (decafs_file_stat (inst.file_id, &stat, client) < 0) {
    if (send_read_result (client, 0, UNABLE_TO_STAT_FILE, NULL) < 0) {
      printf ("\tRead result could not reach client.\n");
    }
    return;
  }

  if ((file_offset = get_file_cursor (fd)) < 0) {
    if (send_read_result (client, 0, FILE_NOT_OPEN_FOR_READ, NULL) < 0) {
      printf ("\tRead result could not reach client.\n");
    }
    return;
  }

  // TODO: make some assertion about max read size here
  // If we are trying to read past EOF or requesting 0 bytes,
  //   return 0 bytes read
  if (file_offset >= (int)stat.size || count == 0) {
    if (send_read_result (client, fd, 0, NULL) < 0) {
      printf ("\tRead result could not reach client.\n");
    }
    return;
  }

  // Save the request id.
  active_read_requests[request_id] = read_request_info (client, inst.file_id,
                                                        fd, buf);
  get_first_stripe (&stripe_id, &stripe_offset, stat.stripe_size,
                    file_offset);

  while (bytes_read < (int)count) {
    printf ("file cursor: %d\n", get_file_cursor(fd));
    if (count - bytes_read > stat.stripe_size - stripe_offset) {
      read_size = stat.stripe_size - stripe_offset;
    }
    else {
      read_size = count - bytes_read;
    }

    printf ("\t(request: %d) sending stripe (%d) information for processing (%d bytes)\n",
               request_id, stripe_id, read_size);

    // TODO: add pathname here, get from persistent meta
    num_chunks += process_read_stripe (request_id, inst.file_id, (char *)"",
                                       stripe_id, stat.stripe_size,
                                       stat.chunk_size,
                                       (uint8_t *)buf + bytes_read,
                                       stripe_offset, read_size);

    set_file_cursor (fd, get_file_cursor (fd) + read_size, client);
    stripe_offset = 0;
    bytes_read += read_size;
    ++stripe_id;
  }

  assert (read_request_exists (request_id));
  active_read_requests[request_id].info.chunks_expected = num_chunks;
  check_read_complete(request_id);
}
Ejemplo n.º 6
0
/**
 * This function is called by all threads to treat to process the request and response.
 * It will also apply the plugins.
 */
void proxenet_process_http_request(sock_t server_socket)
{
	sock_t client_socket;
	request_t req;
	int retcode;
	fd_set rfds;
	struct timespec ts;
	ssl_context_t ssl_context;
	bool is_ssl;
	sigset_t emptyset;
	size_t n;
	
	client_socket = retcode = n = -1;
	
	proxenet_xzero(&req, sizeof(request_t));
	proxenet_xzero(&ssl_context, sizeof(ssl_context_t));

	/* wait for any event on sockets */
	for(;;) {
		
		if (server_socket < 0) {
			xlog(LOG_ERROR, "%s\n", "Sock browser->proxy died unexpectedly");
			break;
		}
		
		ts.tv_sec  = HTTP_TIMEOUT_SOCK;
		ts.tv_nsec = 0;
		
		FD_ZERO(&rfds);
		FD_SET(server_socket, &rfds);
		if (client_socket > 0)
			FD_SET(client_socket, &rfds);

		sigemptyset(&emptyset);
		retcode = pselect(FD_SETSIZE, &rfds, NULL, NULL, &ts, &emptyset);
		
		if (retcode < 0) {
			if (errno == EINTR) {
				continue;
			} else {
				xlog(LOG_CRITICAL, "[thread] pselect returned %d: %s\n", retcode, strerror(errno));
				break;
			}
		}

		if (retcode == 0) {
			break;
		}
		
		is_ssl = ssl_context.use_ssl;
		
		/* is there data from web browser to proxy ? */
		if( FD_ISSET(server_socket, &rfds ) ) {	
			n = - 1;
			
			if(is_ssl) {
				n = proxenet_read_all(server_socket,
						      &req.data,
						      &(ssl_context.server.context));
			} else {
				n = proxenet_read_all(server_socket, &req.data, NULL);
			}
#ifdef DEBUG
			xlog(LOG_DEBUG, "[%d] Got %dB from client (%s)\n", req.id, n, (is_ssl)?"SSL":"PLAIN");
#endif
			
			if (n <= 0) 
				break;

			req.size = n;
			
			/* is connection to server not established ? -> new request */
			if (client_socket < 0) {
			
				retcode = create_http_socket(&req, &server_socket, &client_socket, &ssl_context);
				if (retcode < 0) {
					xlog(LOG_ERROR, "[%d] Failed to create %s->server socket\n", req.id, PROGNAME);
					proxenet_xfree(req.data);
					client_socket = -1;
					break;
				}

				
				if (ssl_context.use_ssl) {
					if (ssl_context.server.is_valid && ssl_context.client.is_valid) {
#ifdef DEBUG
						xlog(LOG_DEBUG, "[%d] SSL interception established\n", req.id);
#endif
						proxenet_xfree(req.data);
						continue;
						
					}
					
					xlog(LOG_ERROR, "[%d] Failed to establish interception\n", req.id);
					proxenet_xfree(req.data);
					client_socket = -1;
					break;
				}
			}
			
			req.type   = REQUEST;
			req.id     = get_new_request_id();

			/* check if request is valid  */
			if (!cfg->proxy.host) {
				if (!is_ssl) {
					if (!is_valid_http_request(&req.data, &req.size)) {
							proxenet_xfree(req.data);
							client_socket = -1;
							break;
					}
				} else {
					set_https_infos(&req);
				}
			}


			if (cfg->verbose) {
				xlog(LOG_INFO, "New request %d to '%s:%d'\n",
				     req.id,
				     req.http_infos.hostname,
				     req.http_infos.port);
				
				if (cfg->verbose > 1)
					xlog(LOG_INFO, "%s %s://%s:%d%s %s\n",
					     req.http_infos.method,
					     req.http_infos.proto,
					     req.http_infos.hostname,
					     req.http_infos.port,
					     req.http_infos.uri,
					     req.http_infos.version);
					     
			}

#ifdef DEBUG
			xlog(LOG_DEBUG, "[%d] Sending buffer %d bytes (%s) - pre-plugins\n",
			     req.id, req.size, (req.http_infos.is_ssl)?"SSL":"PLAIN");
#endif
			/* hook request with all plugins in plugins_list  */
			if ( proxenet_apply_plugins(&req) < 0) {
				/* extremist action: any error on any plugin discard the whole request */
				req.id = 0;
				proxenet_xfree( req.data );
				continue;
			}
			
#ifdef DEBUG
			xlog(LOG_DEBUG, "[%d] Sending buffer %d bytes (%s) - post-plugins\n",
			     req.id, req.size, (req.http_infos.is_ssl)?"SSL":"PLAIN");
#endif
			/* send modified data */
			if (is_ssl) {
				retcode = proxenet_ssl_write(client_socket, req.data, req.size,
							     &(ssl_context.client.context));
			} else {
				retcode = proxenet_write(client_socket, req.data, req.size);
			}

			proxenet_xfree(req.data);

			if (retcode < 0) {
				xlog(LOG_ERROR, "[%d] %s\n", req.id, "Failed to write to server");
				if (req.id)
					req.id = 0;
				break;
			}
			
		} /* end FD_ISSET(data_from_browser) */
		
		
		/* is there data from remote server to proxy ? */
		if( client_socket > 0 && FD_ISSET(client_socket, &rfds ) ) {
			n = -1;

			if (is_ssl)
				n = proxenet_read_all(client_socket, &req.data, &ssl_context.client.context);
			else
				n = proxenet_read_all(client_socket, &req.data, NULL);
			
#ifdef DEBUG
			xlog(LOG_DEBUG, "[%d] Got %dB from server\n", req.id, n);
#endif
			
			if (n <= 0)
				break;

			/* update request data structure */
			req.type   = RESPONSE;
			req.size   = n;
			
			/* execute response hooks */
			if ( proxenet_apply_plugins(&req) < 0) {
				/* extremist action: any error on any plugin discard the whole request */
				req.id = 0;
				proxenet_xfree(req.data);
				continue;
			}

			/* send modified data to client */
			if (is_ssl)
				retcode = proxenet_ssl_write(server_socket, req.data, req.size, &ssl_context.server.context);
			else
				retcode = proxenet_write(server_socket, req.data, req.size);
			
			if (retcode < 0) {
				xlog(LOG_ERROR, "[%d] %s\n", req.id, "proxy->client: write failed");
			}
			
			proxenet_xfree(req.data);

		}  /* end FD_ISSET(data_from_server) */
		
	}  /* end for(;;) { select() } */

	
	if (req.id) {
#ifdef DEBUG
		xlog(LOG_DEBUG, "Free-ing request %d\n", req.id);
#endif
		proxenet_xfree(req.http_infos.method);
		proxenet_xfree(req.http_infos.hostname);
		proxenet_xfree(req.http_infos.uri);
		proxenet_xfree(req.http_infos.version);
	}
	
	/* close client socket */
	if (client_socket > 0) {
#ifdef DEBUG
		xlog(LOG_DEBUG, "Closing proxy->server socket #%d\n", client_socket);
#endif		
		if (ssl_context.client.is_valid) {
			proxenet_ssl_finish(&(ssl_context.client), false);
			close_socket_ssl(client_socket, &ssl_context.client.context);
		
		} else {
			close_socket(client_socket);
		}
	}
	
	
	/* close local socket */
	if (server_socket > 0) {
#ifdef DEBUG
		xlog(LOG_DEBUG, "Closing browser->proxy socket #%d\n", server_socket);
#endif		
		if (ssl_context.server.is_valid) {
			proxenet_ssl_finish(&(ssl_context.server), true);
			close_socket_ssl(server_socket, &ssl_context.server.context);
			
		} else {
			close_socket(server_socket);
		}
	}

	/* and that's all folks */
	return;
}
Ejemplo n.º 7
0
/**
 * This function is called by all threads to treat to process the request and response.
 * It will also apply the plugins.
 *
 * @param server_socket is the socket received by the main thread from the web browser (acting like server
 * to web browser)
 */
void proxenet_process_http_request(sock_t server_socket)
{
        sock_t client_socket;
        request_t req;
        int retcode, n;
        fd_set rfds;
        struct timespec ts;
        ssl_context_t ssl_context;
        bool is_ssl;
        sigset_t emptyset;
        bool is_new_http_connection = false;

        client_socket = retcode = n = -1;
        proxenet_xzero(&req, sizeof(request_t));
        proxenet_xzero(&ssl_context, sizeof(ssl_context_t));

        /* wait for any event on sockets */
        while(proxy_state == ACTIVE) {

                if (server_socket < 0) {
                        xlog(LOG_ERROR, "sock browser->%s (#%d) died unexpectedly\n", PROGNAME, server_socket);
                        break;
                }

                ts.tv_sec  = HTTP_TIMEOUT_SOCK;
                ts.tv_nsec = 0;

                FD_ZERO(&rfds);
                FD_SET(server_socket, &rfds);
                if (client_socket > 0)
                        FD_SET(client_socket, &rfds);

                sigemptyset(&emptyset);
                retcode = pselect(FD_SETSIZE, &rfds, NULL, NULL, &ts, &emptyset);
                if (retcode < 0) {
                        if (errno == EINTR) {
                                continue;
                        } else {
                                xlog(LOG_CRITICAL, "[thread] pselect returned %d: %s\n", retcode, strerror(errno));
                                break;
                        }
                }

                if (retcode == 0) {
                        continue;
                }

                is_ssl = ssl_context.use_ssl;

                /* is there data from web browser to proxy ? */
                if( FD_ISSET(server_socket, &rfds ) ) {

                        if(is_ssl && req.do_intercept) {
                                n = proxenet_read_all(server_socket,
                                                      &req.data,
                                                      &(ssl_context.server.context));
                        } else {
                                n = proxenet_read_all(server_socket, &req.data, NULL);
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "Got %dB from client (%s srv_sock=#%d intercept_flag=%s)\n",
                             n, is_ssl?"SSL":"PLAIN", server_socket,
                             req.do_intercept?"true":"false");
#endif

                        if (n < 0) {
                                xlog(LOG_ERROR, "%s\n", "read() failed, end thread");
                                break;
                        }

                        if (n == 0){
#ifdef DEBUG
                                xlog(LOG_DEBUG, "%s\n", "Socket EOF from client");
#endif
                                break;
                        }


                        /* from here, n can only be positive */
                        req.size = (size_t) n;
                        bytes_sent += n;

                        if (req.id > 0 && !req.do_intercept){
#ifdef DEBUG
                                xlog(LOG_DEBUG, "Intercept disabled for browser->'%s'\n", req.http_infos.hostname);
#endif
                                goto send_to_server;
                        }

                        /* proxy keep-alive */
                        if (req.id > 0){
                                request_t* old_req = (request_t*)proxenet_xmalloc(sizeof(request_t));
                                memcpy(old_req, &req, sizeof(request_t));
                                char* host = proxenet_xstrdup2( req.http_infos.hostname );

                                free_http_infos(&(req.http_infos));

                                if (update_http_infos(&req) < 0){
                                        xlog(LOG_ERROR, "Failed to update HTTP information for request %d\n", req.id);
                                        proxenet_xfree( host );
                                        proxenet_xfree( old_req );
                                        req.id = 0;
                                        break;
                                }

                                if (strcmp( host, req.http_infos.hostname )){
                                        /* reset the client connection parameters */
                                        if (cfg->verbose)
                                                xlog(LOG_INFO, "Reusing sock=%d (old request=%d, old sock=%d) %s/%s\n",
                                                     server_socket, req.id, client_socket, host, req.http_infos.hostname );
                                        proxenet_close_socket(client_socket, &(ssl_context.client));
                                        free_http_infos(&(req.http_infos));
                                        client_socket = -1;
                                }

                                proxenet_xclean( old_req, sizeof(request_t) );
                                proxenet_xfree( host );
                        }

                        req.type = REQUEST;
                        req.id = get_new_request_id();

                        /* is connection to server not established ? -> new request */
                        if ( client_socket < 0) {
                                retcode = create_http_socket(&req, &server_socket, &client_socket, &ssl_context);
                                if (retcode < 0) {
                                        xlog(LOG_ERROR, "Failed to create %s->server socket\n", PROGNAME);
                                        proxenet_xfree(req.data);
                                        req.id = 0;
                                        break;
                                }


                                if (ssl_context.use_ssl) {
                                        req.is_ssl = true;

                                        if (req.do_intercept == false) {
#ifdef DEBUG
                                                xlog(LOG_DEBUG, "SSL interception client <-> %s <-> server disabled\n", PROGNAME);
#endif
                                                proxenet_xfree(req.data);
                                                req.type = REQUEST;
                                                req.id = get_new_request_id();
                                                continue;

                                        } else if (ssl_context.server.is_valid && ssl_context.client.is_valid) {
#ifdef DEBUG
                                                xlog(LOG_DEBUG, "SSL interception client <-> %s <-> server established\n", PROGNAME);
#endif
                                                proxenet_xfree(req.data);
                                                is_new_http_connection = true;
                                                continue;
                                        }

                                        xlog(LOG_ERROR, "%s\n", "Failed to establish interception");
                                        proxenet_xfree(req.data);
                                        break;
                                }

                                is_new_http_connection = true;
                        }



                        /* if proxenet does not relay to another proxy */
                        if (!cfg->proxy.host) {

                                if (is_new_http_connection) {

                                        if (is_ssl) {
                                                /*
                                                 * SSL request fields still have the values gathered in the CONNECT
                                                 * Those values must be updated to reflect the real request
                                                 */
                                                free_http_infos(&(req.http_infos));
                                                retcode = update_http_infos(&req);
                                        } else {
                                                /*
                                                 * Format requests
                                                 * GET http://foo/bar.blah HTTP/1.1 ...
                                                 * into
                                                 * GET /bar.blah HTTP/1.1 ...
                                                 */
                                                retcode = format_http_request(&req.data, &req.size);
                                        }
                                } else {
                                        /* if here, at least 1 request has been to server */
                                        /* so simply forward  */
                                        /* e.g. using HTTP/1.1 100 Continue */
#ifdef DEBUG
                                        xlog(LOG_DEBUG, "Resuming stream '%d'->'%d'\n", client_socket, server_socket);
#endif
                                        free_http_infos(&(req.http_infos));
                                        retcode = update_http_infos(&req);
                                }

                                if (retcode < 0){
                                        xlog(LOG_ERROR, "Failed to update %s information in request %d\n",
                                             is_ssl?"HTTPS":"HTTP", req.id);
                                        proxenet_xfree(req.data);
                                        break;
                                }
                        }


                        if(cfg->ie_compat){
                                if (is_ssl)
                                        retcode = ie_compat_read_post_body(server_socket, &req, &(ssl_context.server.context));
                                else
                                        retcode = ie_compat_read_post_body(server_socket, &req, NULL);
                                if (retcode < 0){
                                        xlog(LOG_ERROR, "%s\n", "Extending IE POST: failed");
                                        proxenet_xfree(req.data);
                                        break;
                                }
                        }


                        /* apply plugins for requests (from browser to server) */
                        if (cfg->verbose) {
                                xlog(LOG_INFO, "%s request to '%s:%d'\n",
                                     is_ssl?"SSL":"plain", req.http_infos.hostname, req.http_infos.port);

                                if (cfg->verbose > 1)
                                        xlog(LOG_INFO, "%s %s %s\n",
                                             req.http_infos.method, req.http_infos.uri, req.http_infos.version);
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "Request %d pre-plugins: buflen:%lu\n",
                             req.id, req.size);
#endif
                        /* hook request with all plugins in plugins_list  */
                        if ( proxenet_apply_plugins(&req) < 0) {
                                /* extremist action: any error on any plugin discard the whole request */
                                proxenet_xfree( req.data );
                                break;
                        }
#ifdef DEBUG
                        xlog(LOG_DEBUG, "Request %d post-plugins: buflen:%lu\n",
                             req.id, req.size);

                        if(cfg->verbose > 2)
                                proxenet_hexdump(req.data, req.size);
#endif

                send_to_server:
                        /* send modified data */
                        if (is_ssl && req.do_intercept) {
                                retcode = proxenet_ssl_write(&(ssl_context.client.context), req.data, req.size);
                        } else {
                                retcode = proxenet_write(client_socket, req.data, req.size);
                        }

                        /* reset data */
                        proxenet_xfree(req.data);
                        req.size = 0;

                        if (retcode < 0) {
                                xlog(LOG_ERROR, "[%d] %s\n", req.id, "Failed to write to server");
                                break;
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "Written %d bytes to server (socket=%s socket #%d)\n",
                             retcode, is_ssl?"SSL":"PLAIN", client_socket);
#endif

                } /* end FD_ISSET(data_from_browser) */


                /* is there data from remote server to proxy ? */
                if( client_socket > 0 && FD_ISSET(client_socket, &rfds ) ) {

                        if(req.is_ssl && req.do_intercept) {
                                n = proxenet_read_all(client_socket, &req.data, &ssl_context.client.context);
                        } else {
                                n = proxenet_read_all(client_socket, &req.data, NULL);
                        }

                        if (n < 0){
                                xlog(LOG_ERROR, "read() %s on cli_sock=#%d failed: %d\n",
                                     is_ssl?"SSL":"PLAIN",
                                     client_socket, n);
                                break;
                        }

                        if (n==0){
#ifdef DEBUG
                                xlog(LOG_DEBUG, "Socket EOF from server (cli_sock=#%d)\n",
                                     client_socket);
#endif
                                break;
                        }

                        /* update request data structure */
                        req.type   = RESPONSE;

                        /* from here, n can only be positive */
                        req.size   = (size_t) n;
                        bytes_recv += n;

                        if (req.do_intercept==false){
#ifdef DEBUG
                                xlog(LOG_DEBUG, "Intercept disabled for '%s'->browser\n", req.http_infos.hostname);
#endif
                                goto send_to_client;
                        }

                        /* apply plugins for response (from server to browser) */
#ifdef DEBUG
                        xlog(LOG_DEBUG, "Response %d pre-plugins: buflen:%lu\n",
                             req.id, req.size);
#endif
                        /* execute response hooks */
                        if ( proxenet_apply_plugins(&req) < 0) {
                                /* extremist action: any error on any plugin discard the whole request */
                                proxenet_xfree(req.data);
                                break;
                        }
#ifdef DEBUG
                        xlog(LOG_DEBUG, "Response %d post-plugins: buflen:%lu\n",
                             req.id, req.size);

                        if(cfg->verbose > 2)
                                proxenet_hexdump(req.data, req.size);
#endif

                send_to_client:
                        /* send modified data to client */
                        if (req.is_ssl && req.do_intercept)
                                retcode = proxenet_ssl_write(&(ssl_context.server.context), req.data, req.size);
                        else
                                retcode = proxenet_write(server_socket, req.data, req.size);

                        if (retcode < 0) {
                                xlog(LOG_ERROR, "[%d] %s\n", req.id, "proxy->client: write failed");
                                proxenet_xfree(req.data);
                                break;
                        }

#ifdef DEBUG
                        xlog(LOG_DEBUG, "Written %d bytes to browser (socket=%s socket #%d)\n",
                             retcode, is_ssl?"SSL":"PLAIN", client_socket);
#endif
                        proxenet_xfree(req.data);

                }  /* end FD_ISSET(data_from_server) */

        }  /* end for(;;) { select() } */


        if (req.id) {
                if (cfg->verbose)
                        xlog(LOG_INFO, "End of request %d, cleaning context\n", req.id);

                free_http_infos(&(req.http_infos));
        }


        /* close client socket */
        if (client_socket > 0) {
                if (cfg->verbose >= 2)
                        xlog(LOG_INFO, "Closing %s->server (fd=#%d)\n", PROGNAME, client_socket);

                proxenet_close_socket(client_socket, &(ssl_context.client));
        }


        /* close local socket */
        if (server_socket > 0) {
                if (cfg->verbose >= 2)
                        xlog(LOG_INFO, "Closing browser->%s (fd=#%d)\n", PROGNAME, server_socket);

                proxenet_close_socket(server_socket, &(ssl_context.server));
        }


#ifdef DEBUG
        xlog(LOG_DEBUG, "Request %d: Structures closed, leaving\n", req.id);
#endif
        /* and that's all folks */
        return;
}
Ejemplo n.º 8
0
/**
 * This function is called right after the configuration was parsed.
 * It simply:
 * - creates the main listening sockets (control and proxy)
 * - initialize the signal mask
 * - initialize all the VMs
 * - fill the plugin list with the valid plugins located in the autoload path
 * - then call the main thread loop
 * - once finished, it also cleans the structures
 *
 * @return 0 if everything went well, -1 otherwise with an error message
 */
int proxenet_start()
{
        sock_t control_socket, listening_socket;
        struct sigaction saction;

        /* create control socket */
        control_socket = proxenet_bind_control_socket();
        if (control_socket < 0) {
                xlog(LOG_CRITICAL, "Cannot create control socket: %s\n", strerror(errno));
                return -1;
        }

        if(cfg->verbose)
                xlog(LOG_INFO, "Control socket: %d\n", control_socket);

        /* create listening socket */
        listening_socket = proxenet_bind_socket(cfg->iface, cfg->port);
        if (listening_socket < 0) {
                xlog(LOG_CRITICAL, "Cannot create bind socket: %s\n", strerror(errno));
                return -1;
        }

        if(cfg->verbose)
                xlog(LOG_INFO, "Bind socket: %d\n", listening_socket);


        /* init everything */
        initialize_sigmask(&saction);

        plugins_list = NULL;
        proxy_state = INACTIVE;
        active_threads_bitmask = 0;

        /* set up plugins */
        if( proxenet_initialize_plugins_list() < 0 )
                return -1;

        /* this call *MUST* succeed or die */
        proxenet_initialize_plugins();

        /* setting request counter  */
        request_id = 0;

        /* we "artificially" allocate an ID 0 so that all new requests will be > 0 */
        /* for the child threads, a request id of 0 means not allocated */
        get_new_request_id();

        init_global_stats();

        /* prepare threads and start looping */
        xloop(listening_socket, control_socket);

        end_global_stats();

        if (cfg->verbose)
                print_global_stats();

        /* clean context */
        proxenet_destroy_plugins_vm();
        proxenet_free_all_plugins();

        proxenet_close_socket(listening_socket, NULL);
        proxenet_close_socket(control_socket, NULL);

        unlink(CFG_CONTROL_SOCK_PATH);
        return 0;
}