summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--segget/connection.cpp51
-rw-r--r--segget/connection.h15
-rw-r--r--segget/distfile.cpp15
-rw-r--r--segget/distfile.h2
-rw-r--r--segget/network.cpp10
-rw-r--r--segget/requestserver.cpp2
-rw-r--r--segget/response.h3
-rw-r--r--segget/scripts/client.py7
-rw-r--r--segget/scripts/functions.py77
-rw-r--r--segget/scripts/net0.py15
-rw-r--r--segget/scriptserver.cpp320
-rw-r--r--segget/scriptserver.h73
-rw-r--r--segget/segget.conf75
-rw-r--r--segget/segget.cpp20
-rw-r--r--segget/segget.h1
-rw-r--r--segget/settings.cpp3
-rw-r--r--segget/settings.h6
17 files changed, 662 insertions, 33 deletions
diff --git a/segget/connection.cpp b/segget/connection.cpp
index 9380cf4..2f8399c 100644
--- a/segget/connection.cpp
+++ b/segget/connection.cpp
@@ -25,6 +25,7 @@
*/
#include "connection.h"
+long script_waiting_connection_num=-1;
uint Tconnection::total_connections=0;
Tconnection connection_array[MAX_CONNECTS];
time_t prev_time;
@@ -35,9 +36,8 @@ void init_connections(){
};
}
-void Tconnection::start(CURLM *cm, uint network_number, uint distfile_num, Tsegment *started_segment, uint best_mirror_num){
+int Tconnection::start(CURLM *cm, uint network_number, uint distfile_num, Tsegment *started_segment, uint best_mirror_num){
try{
- stats.active_connections_counter++;
segment=started_segment;
debug("Starting connection for distfile: "+segment->parent_distfile->name);
mirror_num=best_mirror_num;
@@ -55,7 +55,6 @@ void Tconnection::start(CURLM *cm, uint network_number, uint distfile_num, Tsegm
}
Tmirror *Pcurr_mirror;
- string url;
switch (network_array[network_num].network_mode){
case MODE_REMOTE:{
url=segment->parent_distfile->url_list[mirror_num];
@@ -74,16 +73,24 @@ void Tconnection::start(CURLM *cm, uint network_number, uint distfile_num, Tsegm
}
debug(" URL:"+url);
+ if (run_user_python_script(connection_num)){
+ return REJECTED_BY_USER_PYTHON_SCRIPT;
+ }
+
debug("aaaaa");
Pcurr_mirror->start();
debug("bbbbb");
network_array[network_num].connect();
debug("ccccc");
+
+ stats.active_connections_counter++;
segment->prepare_for_connection(cm, connection_num, network_num, distfile_num, url);
debug("Started connection for distfile: "+segment->parent_distfile->name);
+ return 0;
}catch(...){
error_log("Error in connection.cpp: start()");
}
+ return ERROR_WHILE_PREPARING_CONNECTION;
}
/*
string explain_curl_error(int error_code){
@@ -98,6 +105,17 @@ string explain_curl_error(int error_code){
void Tconnection::stop(CURLcode connection_result){
try{
stats.active_connections_counter--;
+ Tmirror *Pcurr_mirror;
+ switch (network_array[network_num].network_mode){
+ case MODE_REMOTE:
+ case MODE_CORAL_CDN:{
+ Pcurr_mirror=find_mirror(strip_mirror_name(url));
+ break;
+ }
+ default:{
+ Pcurr_mirror=&network_array[network_num].benchmarked_mirror_list[mirror_num];
+ }
+ }
debug("Finished connection for distfile: "+segment->parent_distfile->name+" Segment#:"+toString(segment->segment_num)+" Network#"+toString(network_num)+" Status: "+toString(connection_result));
if (connection_result){
string error_str=curl_easy_strerror(connection_result);
@@ -105,21 +123,26 @@ void Tconnection::stop(CURLcode connection_result){
error_log("Finished connection for distfile: "+segment->parent_distfile->name+" Segment#:"+toString(segment->segment_num)+" Network#"+toString(network_num)+" Status: "+toString(connection_result));
error_log(" ERROR "+toString(connection_result)+": "+error_str);
}
-
- msg_clean_connection(connection_num);
active=false;
network_array[network_num].disconnect();
// network_array[network_num].benchmarked_mirror_list[mirror_num].stop();
segment->segment_file.close();
if (connection_result==0){
if (! segment->segment_verification_is_ok()){
+ connection_result=CURLE_READ_ERROR;
+ Pcurr_mirror->stop(time_left_from(connection_array[connection_num].start_time),0);
debug("curl_lies - there is a problem downloading segment");
error_log("curl_lies - there is a problem downloading segment");
- connection_result=CURLE_READ_ERROR;
+ }else{
+ Pcurr_mirror->stop(time_left_from(connection_array[connection_num].start_time),segment->segment_size);
}
+ }else{
+ Pcurr_mirror->stop(time_left_from(connection_array[connection_num].start_time),0);
}
-
segment->parent_distfile->active_connections_num--;
+
+ msg_clean_connection(connection_num);
+
/*
Tmirror *Pcurr_mirror;
if (network_array[network_num].network_mode==MODE_LOCAL){
@@ -131,18 +154,6 @@ void Tconnection::stop(CURLcode connection_result){
}
*/
- Tmirror *Pcurr_mirror;
- switch (network_array[network_num].network_mode){
- case MODE_REMOTE:
- case MODE_CORAL_CDN:{
- Pcurr_mirror=find_mirror(strip_mirror_name(segment->url));
- break;
- }
- default:{
- Pcurr_mirror=&network_array[network_num].benchmarked_mirror_list[mirror_num];
- }
- }
-
timeval now_time;
gettimeofday(&now_time,NULL);
@@ -170,7 +181,6 @@ void Tconnection::stop(CURLcode connection_result){
// error -> start downloading again
// msg_status2(segment->connection_num, toString(connection_result)+"]- Failed download "+segment->file_name);
debug(toString(connection_result)+"]- Failed download "+segment->url);
- Pcurr_mirror->stop(time_left_from(connection_array[connection_num].start_time),0);
if (segment->try_num>=settings.max_tries){
segment->status=SFAILED;
segment->parent_distfile->status=DFAILED;
@@ -183,7 +193,6 @@ void Tconnection::stop(CURLcode connection_result){
log("Succesfully downloaded "+segment->file_name+" on connection#"+toString(connection_num));
debug(" Successful download "+segment->url);
// already done earlier in this function Pcurr_mirror=find_mirror(strip_mirror_name(segment->url));
- Pcurr_mirror->stop(time_left_from(connection_array[connection_num].start_time),segment->segment_size);
segment->status=SDOWNLOADED;
segment->parent_distfile->inc_dld_segments_count(segment);
};
diff --git a/segget/connection.h b/segget/connection.h
index bdb4a59..a758ee6 100644
--- a/segget/connection.h
+++ b/segget/connection.h
@@ -33,6 +33,7 @@ class Tsegment;
#include "segment.h"
#include "utils.h"
#include "networkbroker.h"
+#include "scriptserver.h"
using namespace std;
@@ -40,12 +41,14 @@ class Tconnection{
static uint total_connections;
private:
Tnetwork_distfile_broker_phases connection_start_time_network_phase_for_pf_networks;
+ public:
uint network_num;
uint mirror_num;
- public:
+ string url;
ulong total_dld_bytes;
ulong bytes_per_last_interval;
uint connection_num;
+ ulong max_speed_limit;
bool active;
timeval start_time;
Tsegment *segment;
@@ -53,18 +56,24 @@ class Tconnection{
connection_start_time_network_phase_for_pf_networks(E_USE_AS_LOCAL_MIRRORS),
network_num(0),
mirror_num(0),
+ url(""),
total_dld_bytes(0),
bytes_per_last_interval(0),
connection_num(0),
+ max_speed_limit(0),
active(0),
start_time(),
- segment(0){};
- void start(CURLM *cm, uint network_number, uint distfile_num, Tsegment *started_segment, uint best_mirror_num);
+ segment(0)
+ {};
+ Tconnection(const Tconnection &L); // copy constructor
+ Tconnection & operator=(const Tconnection &L);
+ int start(CURLM *cm, uint network_number, uint distfile_num, Tsegment *started_segment, uint best_mirror_num);
void stop(CURLcode connection_result);
void inc_bytes_per_last_interval(ulong new_bytes_count);
void show_connection_progress(ulong time_diff);
};
+extern long script_waiting_connection_num;
extern time_t prev_time;
extern Tconnection connection_array[MAX_CONNECTS];
void init_connections();
diff --git a/segget/distfile.cpp b/segget/distfile.cpp
index 11b7be7..4f56bbe 100644
--- a/segget/distfile.cpp
+++ b/segget/distfile.cpp
@@ -340,8 +340,12 @@ bool Tdistfile::choose_best_mirror(CURLM* cm, uint connection_num, uint network_
debug("Downloading from BEST_MIRROR:"+url_str);
// Pbest_mirror->start();
// active_connections_num++;
- connection_array[connection_num].start(cm, network_num, num, &dn_segments[seg_num], best_mirror_num);
- return R_R_DOWNLOAD_STARTED;
+ int result=connection_array[connection_num].start(cm, network_num, num, &dn_segments[seg_num], best_mirror_num);
+ if (result){
+ return result;
+ }else{
+ return R_R_DOWNLOAD_STARTED;
+ }
}
else{
error_log("Can't choose mirror for segment:"+dn_segments[seg_num].file_name);
@@ -384,7 +388,12 @@ bool Tdistfile::choose_best_local_mirror(CURLM* cm, uint connection_num, uint ne
if (best_mirror_num!=-1){
debug("Downloading from BEST_LOCAL_MIRROR:"+network_array[network_num].benchmarked_mirror_list[best_mirror_num].url);
// active_connections_num++;
- connection_array[connection_num].start(cm, network_num, num, &dn_segments[seg_num], best_mirror_num);
+ int result=connection_array[connection_num].start(cm, network_num, num, &dn_segments[seg_num], best_mirror_num);
+ if (result){
+ return result;
+ }else{
+ return R_R_DOWNLOAD_STARTED;
+ }
return R_R_DOWNLOAD_STARTED;
}
else{
diff --git a/segget/distfile.h b/segget/distfile.h
index a14e137..69f20c7 100644
--- a/segget/distfile.h
+++ b/segget/distfile.h
@@ -91,10 +91,10 @@ long is_symlink_restricted(string distfile_name);
class Tdistfile{
private:
- uint dld_segments_count;
bool choose_best_local_mirror(CURLM* cm, uint connection_num, uint network_num, uint seg_num);
bool choose_best_mirror(CURLM* cm, uint connection_num, uint network_num, uint seg_num);
public:
+ uint dld_segments_count;
Tnetwork_distfile_broker network_distfile_brokers_array[MAX_NETWORKS];
string json_data;
// bool downloaded;
diff --git a/segget/network.cpp b/segget/network.cpp
index ea417ce..ccde337 100644
--- a/segget/network.cpp
+++ b/segget/network.cpp
@@ -53,8 +53,12 @@ void Tnetwork::load_mirror_list(){
benchmarked_mirror_list.push_back(cur_mirror);
debug("LOCAL_MIRROR_ADDED:"+mirror_line);
}
- }
- catch(...){
+ }catch(ifstream::failure e){
+ if (!file.eof()){
+ error_log("Mirror list file: "+mirror_list_file_name+" was opened, but an error occured while reading from it.");
+ return;
+ }
+ }catch(...){
error_log("Mirror list file: "+mirror_list_file_name+" was opened, but an error occured while reading from it.");
}
}catch(...){
@@ -106,7 +110,7 @@ void Tnetwork::init(uint priority_value){
{
conf.set("network_mirrors","only_local_when_possible",only_local_when_possible);
load_mirror_list();
- log("Settings: Network"+toString(network_num)+" local mirror_list size:"+toString(mirror_list.size()));
+ log("Settings in file:network"+toString(network_num)+"_mirrors.conf local mirror_list size:"+toString(benchmarked_mirror_list.size()));
break;
};
case MODE_PROXY_FETCHER:
diff --git a/segget/requestserver.cpp b/segget/requestserver.cpp
index de365d2..fd1111f 100644
--- a/segget/requestserver.cpp
+++ b/segget/requestserver.cpp
@@ -24,7 +24,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "proxyfetcher.h"
+#include "requestserver.h"
void *run_request_server(void * ){
try{
diff --git a/segget/response.h b/segget/response.h
index 77ec9fe..fbeb4f5 100644
--- a/segget/response.h
+++ b/segget/response.h
@@ -56,6 +56,9 @@ using namespace std;
#define DO_NOT_ALLOW_REMOTE_NETWORKS 204
#define ALLOW_LOWER_PRIORITY_NETWORKS 205
+#define REJECTED_BY_USER_PYTHON_SCRIPT 301
+#define ERROR_WHILE_PREPARING_CONNECTION 302
+
int decode_server_response(string server_response);
#endif \ No newline at end of file
diff --git a/segget/scripts/client.py b/segget/scripts/client.py
new file mode 100644
index 0000000..87b97bf
--- /dev/null
+++ b/segget/scripts/client.py
@@ -0,0 +1,7 @@
+# TCP client example
+from functions import *
+from net0 import *
+#user_script
+
+schedule()
+accept_segment() \ No newline at end of file
diff --git a/segget/scripts/functions.py b/segget/scripts/functions.py
new file mode 100644
index 0000000..07fe90a
--- /dev/null
+++ b/segget/scripts/functions.py
@@ -0,0 +1,77 @@
+import sys
+import socket
+
+def get(var_name):
+ print("GET::"+var_name)
+ client_socket.send ("g<c>"+var_name)
+ data = client_socket.recv(512)
+ print "RECIEVED:" , data
+ #connection.num,
+ #connection.max_speed_limit,
+ #network.num,
+ #network.active_connections_count,
+ #distfile.size,
+ #distfile.dld_segments_count,
+ #distfile.segments_count,
+ #distfile.active_connections_count,
+ #segment.num,
+ #segment.try_num,
+ #segment.size,
+ if ((var_name=="connection.url") or (var_name=="distfile.name") or (var_name=="segment.range")):
+ return data
+ else:
+ return int(data)
+
+def set(var_name,var_value):
+ var_value_str=str(var_value);
+ print("SET::"+var_name+"="+var_value_str)
+ client_socket.send ("s<c>"+var_name+"<n>"+var_value_str)
+ data = client_socket.recv(512)
+ print "RECIEVED:" , data
+ if (data=="o<r>"):
+ return 0
+ else:
+ return 1
+
+def accept_segment():
+ print "Accepting segment"
+ client_socket.send ("a<c>")
+ client_socket.close()
+ sys.exit(0)
+
+def reject_segment():
+ print "Rejecting segment"
+ client_socket.send ("r<c>")
+ client_socket.close()
+ sys.exit(0)
+# in case users forget to use quotes
+class Tconnection:
+ num="connection.num"
+ max_speed_limit="connection.max_speed_limit"
+ url="connection.url"
+
+class Tnetwork:
+ num="network.num"
+ mode="network.mode"
+ active_connections_count="network.active_connections_count"
+
+class Tdistfile:
+ name="distfile.name"
+ size="distfile.size"
+ dld_segments_count="distfile.dld_segments_count"
+ segments_count="distfile.segments_count"
+ active_connections_count="distfile.active_connections_count"
+
+class Tsegment:
+ num="segment.num"
+ try_num="segment.try_num"
+ size="segment.size"
+ range="segment.range"
+
+connection=Tconnection
+network=Tnetwork
+distfile=Tdistfile
+segment=Tsegment
+
+client_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+client_socket.connect("/tmp/segget_script_socket") \ No newline at end of file
diff --git a/segget/scripts/net0.py b/segget/scripts/net0.py
new file mode 100644
index 0000000..8d87955
--- /dev/null
+++ b/segget/scripts/net0.py
@@ -0,0 +1,15 @@
+from functions import *
+import time;
+def schedule():
+ localtime = time.localtime(time.time());
+ hour=localtime[3];
+ # disable downloading distfiles that have size more than 5 000 000 bytes
+ # from 8-00 to 22-00.
+ if hour>8 and hour<21 and (get("distfile.size"))>5000000:
+ print "reject because distfile is too big"
+ reject_segment()
+ # set speed limit 50 000 cps for distfiles larger than 1 000 000 bytes
+ if get("distfile.size")>1000000:
+ print "limit connection speed"
+ set(connection.max_speed_limit, 50000)
+ accept_segment() \ No newline at end of file
diff --git a/segget/scriptserver.cpp b/segget/scriptserver.cpp
new file mode 100644
index 0000000..44173d7
--- /dev/null
+++ b/segget/scriptserver.cpp
@@ -0,0 +1,320 @@
+/*
+* Copyright (C) 2010 Robin H.Johnson, Ovechko Kostyantyn <fastinetserver@gmail.com>.
+*
+* Project: IDFetch.
+* Developer: Ovechko Kostyantyn Olexandrovich (Kharkiv State Technical University of Construction and Architecture, Ukraine).
+* Mentor: Robin H. Johnson (Gentoo Linux: Developer, Trustee & Infrastructure Lead).
+* Mentoring organization: Gentoo Linux.
+* Sponsored by GSOC 2010.
+*
+* This file is part of Segget.
+*
+* Segget is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* Segget is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with Segget; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "scriptserver.h"
+
+map<std::string, Tvar_nums> variables_;
+
+#define RESPONSE_OK "o<r>";
+#define RESPONSE_UNKNOWN_VARIABLE "u<r>";
+#define RESPONSE_ERROR "e<r>";
+
+#define ACCEPT_SEGMENT 0;
+#define ERROR_HAPPEND_SO_ACCEPT_SEGMENT 0;
+#define REJECT_SEGMENT 1;
+
+FILE * stderr_file;
+FILE * stdout_file;
+int script_server_sockfd, script_client_sockfd;
+
+string set(uint connection_num, string var_name_and_value){
+ try{
+ string var_name, var_value;
+ if (! split("<n>",var_name_and_value,var_name,var_value)){
+ map<string,Tvar_nums>::const_iterator ci = variables_.find(var_name);
+ if (ci == variables_.end()){
+ return RESPONSE_UNKNOWN_VARIABLE;
+ }else{
+ switch (ci->second){
+ case CONNECTION_MAX_SPEED_LIMIT:{
+ ulong new_max_speed_limit=atol(var_value.c_str());
+ if (new_max_speed_limit==0){
+ error_log("Error in scriptserver.cpp: set("+var_name+"="
+ +var_value+"): Can't convert "+var_value+" to integer");
+ return RESPONSE_ERROR;
+ }else{
+ connection_array[connection_num].max_speed_limit=new_max_speed_limit;
+ debug("set("+var_name+"="+var_value+")");
+ return RESPONSE_OK;
+ }
+ }
+ default:{
+ error_log("Error in scriptserver.cpp: set("+var_name+"="
+ +var_value+"): UNKNOWN VARIABLE");
+ return RESPONSE_UNKNOWN_VARIABLE;
+ }
+ }
+ }
+ }
+ return RESPONSE_ERROR;
+ }catch(...){
+ error_log("Error in scriptserver.cpp: set()");
+ return RESPONSE_ERROR;
+ }
+}
+
+string get(uint connection_num, string var_name){
+ try{
+ map<string,Tvar_nums>::const_iterator ci = variables_.find(var_name);
+ if (ci == variables_.end()){
+ return RESPONSE_UNKNOWN_VARIABLE;
+ }else{
+ switch (ci->second){
+ case DISTFILE_NAME:{
+ return connection_array[connection_num].segment->parent_distfile->name;
+ }
+ case DISTFILE_SIZE:{
+ return toString(connection_array[connection_num].segment->parent_distfile->size);
+ }
+ case DISTFILE_DLD_SEGMENTS_COUNT:{
+ return toString(connection_array[connection_num].segment->parent_distfile->dld_segments_count);
+ }
+ case DISTFILE_SEGMENTS_COUNT:{
+ return toString(connection_array[connection_num].segment->parent_distfile->segments_count);
+ }
+ case DISTFILE_ACTIVE_CONNECTIONS_COUNT:{
+ return toString(connection_array[connection_num].segment->parent_distfile->active_connections_num);
+ }
+ case SEGMENT_NUM:{
+ return toString(connection_array[connection_num].segment->segment_num);
+ }
+ case SEGMENT_TRY_NUM:{
+ return toString(connection_array[connection_num].segment->try_num);
+ }
+ case SEGMENT_SIZE:{
+ return toString(connection_array[connection_num].segment->segment_size);
+ }
+ case SEGMENT_RANGE:{
+ return connection_array[connection_num].segment->range;
+ }
+ case CONNECTION_NUM:{
+ return toString(connection_num);
+ }
+ case CONNECTION_URL:{
+ return connection_array[connection_num].url;
+ }
+ case NETWORK_NUM:{
+ return toString(connection_array[connection_num].network_num);
+ }
+ case NETWORK_MODE:{
+ return toString(network_array[connection_array[connection_num].network_num].network_mode);
+ }
+ case NETWORK_ACTIVE_CONNECTIONS_COUNT:{
+ return toString(network_array[connection_array[connection_num].network_num].active_connections_num);
+ }
+ default: return RESPONSE_UNKNOWN_VARIABLE; //unknown variable
+ }
+ }
+ return RESPONSE_ERROR;
+ }catch(...){
+ error_log("Error in scriptserver.cpp: get()");
+ return RESPONSE_ERROR;
+ }
+}
+void init_variables(){
+ try{
+ variables_["connection.num"]=CONNECTION_NUM;
+ variables_["connection.url"]=CONNECTION_URL;
+ variables_["connection.max_speed_limit"]=CONNECTION_MAX_SPEED_LIMIT;
+ variables_["network.num"]=NETWORK_NUM;
+ variables_["network.mode"]=NETWORK_MODE;
+ variables_["network.active_connections_count"]=NETWORK_ACTIVE_CONNECTIONS_COUNT;
+ variables_["distfile.name"]=DISTFILE_NAME;
+ variables_["distfile.size"]=DISTFILE_SIZE;
+ variables_["distfile.dld_segments_count"]=DISTFILE_DLD_SEGMENTS_COUNT;
+ variables_["distfile.segments_count"]=DISTFILE_SEGMENTS_COUNT;
+ variables_["distfile.active_connections_count"]=DISTFILE_ACTIVE_CONNECTIONS_COUNT;
+ variables_["segment.num"]=SEGMENT_NUM;
+ variables_["segment.try_num"]=SEGMENT_TRY_NUM;
+ variables_["segment.size"]=SEGMENT_SIZE;
+ variables_["segment.range"]=SEGMENT_RANGE;
+// variables_[""]=;
+ }catch(...){
+ error_log("Error in scriptserver.cpp: init_variables()");
+ }
+}
+void send(int fd, string response){
+ try{
+ if (write(fd, response.c_str(), response.length())!=(int)response.length()){
+ error_log("Error in scriptserver.cpp: send(): response msg size and sent data size are different.");
+ };
+ }catch(...){
+ error_log("Error in scriptserver.cpp: send()");
+ }
+}
+
+void killscript(int pID){
+ try{
+ debug("Before killing script");
+/* int killReturn = kill( pID, SIGKILL); // Kill child process
+ if( killReturn == ESRCH){ // pid does not exist
+ error_log("Python script does not exist!");
+ }else if( killReturn == EPERM){ // No permission to send signal
+ error_log("No permission to kill python script");
+ }else debug("Signal to kill python script sent. All Ok!");
+*/
+ waitpid(pID, NULL, 0);
+ close(script_server_sockfd);
+ close(script_client_sockfd);
+ debug("After killing script");
+ }catch(...){
+ error_log("Error in scriptserver.cpp: killscript()");
+ }
+}
+
+bool run_user_python_script(uint connection_num){
+ pid_t pID;
+ try{
+ init_variables();
+ socklen_t server_len, client_len;
+ struct sockaddr_un server_address;
+ struct sockaddr_un client_address;
+
+ int result;
+ fd_set readfds, testfds;
+
+ unlink("/tmp/segget_script_socket");
+ // Create and name a socket for the server:
+ script_server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ server_address.sun_family = AF_UNIX;
+ strcpy(server_address.sun_path, "/tmp/segget_script_socket");
+ server_len = sizeof(server_address);
+ bind(script_server_sockfd, (struct sockaddr *)&server_address, server_len);
+ //Create a connection queue and initialize readfds to handle input from server_sockfd:
+ listen(script_server_sockfd, 5);
+ FD_ZERO(&readfds);
+ FD_SET(script_server_sockfd, &readfds);
+
+ pID = fork();
+ if (pID == 0){ // child
+ alarm(2); // 2 second limit for script to execute
+ stderr_file = fopen((settings.logs_dir+"/net"
+ +toString(connection_array[connection_num].network_num)
+ +"_script_stderr.log").c_str(), "a+");
+ if(stderr_file) {
+ dup2(fileno(stderr_file), 2);
+ fclose(stderr_file);
+ }
+ stdout_file = fopen((settings.logs_dir+"/net"
+ +toString(connection_array[connection_num].network_num)
+ +"_script_stdout.log").c_str(), "a+");
+ if(stdout_file) {
+ dup2(fileno(stdout_file), 1);
+ fclose(stdout_file);
+ }
+ system((settings.python_path+" /home/mona/idfetcha/scripts/client.py").c_str());
+ _exit(0);
+ }else{
+ if (pID < 0){ // failed to fork
+ error_log("Error in scriptserver.cpp: failed to fork");
+ return 0;
+ }
+ }
+
+ error_log("Created pid:"+toString(pID));
+ // parent
+ //Now wait for clients and requests. Because you have passed a null pointer as the timeout parameter, no timeout will occur. The program will exit and report an error if select returns a value less than 1:
+ struct timeval user_script_start_time;
+ gettimeofday(&user_script_start_time,NULL);
+
+ while(1000>time_left_from(user_script_start_time)) {
+ int fd;
+ int nread;
+ testfds = readfds;
+
+ debug("scriptserver is waiting for connections");
+ struct timeval timeout;
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+
+ result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, &timeout);
+ if(result < 1) {
+ error_log("Error in scriptserver.cpp: run_script_server(): error on select ");
+ killscript(pID);
+ return ERROR_HAPPEND_SO_ACCEPT_SEGMENT;
+ }
+ //Once you know you’ve got activity, you can find which descriptor it’s on by checking each in turn using FD_ISSET:
+ for(fd = 0; fd < FD_SETSIZE; fd++) {
+ if(FD_ISSET(fd,&testfds)) {
+ //If the activity is on server_sockfd, it must be a request for a new connection, and you add the associated client_sockfd to the descriptor set:
+ if (fd==script_server_sockfd){
+ debug("new script client - read");
+ client_len = sizeof(client_address);
+ script_client_sockfd = accept(script_server_sockfd,
+ (struct sockaddr *)&client_address, &client_len);
+ FD_SET(script_client_sockfd, &readfds);
+ debug("adding script client on fd:"+toString(script_client_sockfd));
+ break;
+ }else{
+ script_client_sockfd=fd;
+ ioctl(fd, FIONREAD, &nread);
+ if(nread == 0) {
+ debug("removing script client from fd:"+toString(fd));
+ }else{
+ char buffer[100000]="";
+ if (nread!=read(fd, &buffer, nread)){
+ error_log("Error in scriptserver.cpp : run_script_server(): Not all data has been read from script-client");
+ }
+ string recv_msg=noupper(buffer);
+ debug("SCRIPT-SERVER RECIVED:"+recv_msg);
+ string command, arguments, send_response;
+ if (! split("<c>",recv_msg,command,arguments)){
+ switch (command[0]){
+ case 'g':{
+ debug("getting: "+arguments);
+ send(fd,get(connection_num,arguments));
+ break;
+ }
+ case 's':{
+ debug("setting: "+arguments);
+ send(fd,set(connection_num,arguments));
+ break;
+ }
+ case 'a':{
+ debug("accepting segment: ");
+ killscript(pID);
+ return ACCEPT_SEGMENT;
+ }
+ case 'r':{
+ debug("rejecting segment: ");
+ killscript(pID);
+ return REJECT_SEGMENT;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ killscript(pID);
+ return ACCEPT_SEGMENT;
+ }catch(...){
+ error_log("Error in scriptserver.cpp: run_script_server()");
+ return ERROR_HAPPEND_SO_ACCEPT_SEGMENT;
+ }
+ killscript(pID);
+} \ No newline at end of file
diff --git a/segget/scriptserver.h b/segget/scriptserver.h
new file mode 100644
index 0000000..4b3c916
--- /dev/null
+++ b/segget/scriptserver.h
@@ -0,0 +1,73 @@
+/*
+* Copyright (C) 2010 Robin H.Johnson, Ovechko Kostyantyn <fastinetserver@gmail.com>.
+*
+* Project: IDFetch.
+* Developer: Ovechko Kostyantyn Olexandrovich (Kharkiv State Technical University of Construction and Architecture, Ukraine).
+* Mentor: Robin H. Johnson (Gentoo Linux: Developer, Trustee & Infrastructure Lead).
+* Mentoring organization: Gentoo Linux.
+* Sponsored by GSOC 2010.
+*
+* This file is part of Segget.
+*
+* Segget is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* Segget is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with Segget; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef __SCRIPTSERVER_H__
+#define __SCRIPTSERVER_H__
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <stdio.h>
+//#include <netinet/in.h>
+//#include <arpa/inet.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <json/json.h>
+#include "tui.h"
+#include "pkg.h"
+
+enum Tvar_nums{
+ CONNECTION_NUM,
+ CONNECTION_URL,
+ CONNECTION_MAX_SPEED_LIMIT,
+ NETWORK_NUM,
+ NETWORK_MODE,
+ NETWORK_ACTIVE_CONNECTIONS_COUNT,
+ DISTFILE_NAME,
+ DISTFILE_SIZE,
+ DISTFILE_DLD_SEGMENTS_COUNT,
+ DISTFILE_SEGMENTS_COUNT,
+ DISTFILE_ACTIVE_CONNECTIONS_COUNT,
+ SEGMENT_NUM,
+ SEGMENT_TRY_NUM,
+ SEGMENT_SIZE,
+ SEGMENT_RANGE
+};
+
+extern map<std::string, Tvar_nums> variables_;
+
+extern FILE *stdin;
+extern FILE *stdout;
+extern FILE *stderr;
+
+//void *run_script_server(void * );
+bool run_user_python_script(uint connection_num);
+#endif \ No newline at end of file
diff --git a/segget/segget.conf b/segget/segget.conf
index 4cac4a3..616ce1e 100644
--- a/segget/segget.conf
+++ b/segget/segget.conf
@@ -279,6 +279,81 @@ request_ip=127.0.0.1
# request_port=10000
request_port=10000
+[scripting_and_scheduling]
+# Segget provides Python scripting functionalyty to support scheduling.
+# Each time segget tries to start a new connection certain network it calls
+# a python script (client.py) to accept or reject this connection and
+# if necessary adjusts its settings.
+
+# PYTHON_PATH
+# Define path to python
+# Default:
+# python_path=/usr/bin/python
+python_path=/usr/bin/python
+
+# SCRIPTS_DIR
+# Define path to a dir with python scripts. Before establishing connection for
+# a particular segment via network# segget checks SCRIPTS_DIR.
+# If SCRIPTS_DIR contains net#.py file, segget will launch schedule() function
+# from this file to apply settings for connetion and accept or reject this
+# segment for the moment. net#.py file is a causual python script file
+# with a user-writen schedule() function.
+# It's necessary to import functions before using get("variable"),
+# set("variable",value), accept_segment() and reject_segment() in schedule().
+# get() function can obtain values for the following variables:
+# connection.num, connection.url, connection.max_speed_limit,
+# network.num, network.mode, network.active_connections_count,
+# distfile.name, distfile.size, distfile.dld_segments_count,
+# distfile.segments_count, distfile.active_connections_count,
+# segment.num, segment.try_num, segment.size, segment.range
+# set() function can change connection.max_speed_limit, see example:
+# -----------------EXAMPLE STARTS-----------------
+# from functions import *
+# import time;
+# def schedule():
+# localtime = time.localtime(time.time());
+# hour=localtime[3];
+# # disable downloading distfiles that have size more than 5 000 000 bytes
+# # from 8-00 to 22-00.
+# if hour>8 and hour<21 and (get("distfile.size"))>5000000:
+# print "reject because distfile is too big"
+# reject_segment()
+# # set speed limit 50 000 cps for distfiles larger than 1 000 000 bytes
+# if get("distfile.size")>1000000:
+# print "limit connection speed"
+# set(connection.max_speed_limit, 50000)
+# accept_segment()
+# -----------------EXAMPLE ENDS-----------------
+# From example above localtime returns following tuple:
+# Index Attributes Values
+# 0 tm_year e.i.: 2008
+# 1 tm_mon 1 to 12
+# 2 tm_mday 1 to 31
+# 3 tm_hour 0 to 23
+# 4 tm_min 0 to 59
+# 5 tm_sec 0 to 61 (60 or 61 are leap-seconds)
+# 6 tm_wday 0 to 6 (0 is Monday)
+# 7 tm_yday 1 to 366 (Julian day)
+# 8 tm_isdst -1, 0, 1, -1 means library determines DST
+# Therefore localtime[3] provides hours.
+# Segment will be accecpted by default if it was neither accepted nor rejected
+# during the schedule() function.
+# sagget saves logs of resulting stdout and stderr in the log folder
+# separatly for each network. Hence, if there's an error in net3.py file python
+# error message would be saved to net3_script_stderr.log. Results of print would
+# be saved in net3_script_stdout.log.
+# Default:
+# scripts_dir=./scripts
+scripts_dir=./scripts
+
+# script_socket_path
+# Segget uses AF_UNIX domain sockets for communication with python.
+# Specify path for the socket on your filesystem.
+# NOTE !: Default value can NOT be changed yet (option under development).
+# Default:
+# script_socket_path=/tmp/segget_script_socket
+script_socket_path=/tmp/segget_script_socket
+
[logs]
# LOGS_DIR
# Define a dir to store log files.
diff --git a/segget/segget.cpp b/segget/segget.cpp
index dd5a626..7160c60 100644
--- a/segget/segget.cpp
+++ b/segget/segget.cpp
@@ -336,7 +336,18 @@ void launch_request_server_thread(){
debug_no_msg("request_server_thread launched");
}
}
-
+/*
+void launch_script_server_thread(){
+// if (settings.request_ip!="none"){
+ pthread_t script_server_thread;
+ int iret1;
+ debug_no_msg("Creating script_server_thread.");
+// proxy_fetcher_server_thread.init();
+ iret1 = pthread_create( &script_server_thread, NULL, run_script_server, (void*) NULL);
+ debug_no_msg("script_server_thread launched");
+// }
+}
+*/
void segget_exit(int sig){
try{
endwin();
@@ -394,6 +405,13 @@ int routine(){
}catch(...){
error_log_no_msg("Error in segget.cpp launch_proxy_fetcher_server_thread failed");
}
+/*
+ try{
+ launch_script_server_thread();
+ }catch(...){
+ error_log_no_msg("Error in segget.cpp launch_script_server_thread failed");
+ }
+*/
try{
launch_proxy_fetcher_server_thread();
}catch(...){
diff --git a/segget/segget.h b/segget/segget.h
index 4edf30e..b74c458 100644
--- a/segget/segget.h
+++ b/segget/segget.h
@@ -56,6 +56,7 @@
#include "ui_server.h"
#include "proxyfetcher.h"
#include "requestserver.h"
+#include "scriptserver.h"
using namespace std;
diff --git a/segget/settings.cpp b/segget/settings.cpp
index e4415c8..8a4a324 100644
--- a/segget/settings.cpp
+++ b/segget/settings.cpp
@@ -127,6 +127,9 @@ void Tsettings::init(){
conf.set("request_server","request_ip",request_ip);
conf.set("request_server","request_port",request_port,1,65535);
+ conf.set("scripting_and_scheduling","python_path",python_path);
+ conf.set("scripting_and_scheduling","scripts_dir",scripts_dir);
+
conf.clear();
}catch(...){
error_log_no_msg("Error in settings.cpp: init()");
diff --git a/segget/settings.h b/segget/settings.h
index f7c2e95..38fb115 100644
--- a/segget/settings.h
+++ b/segget/settings.h
@@ -79,6 +79,9 @@ class Tsettings{
//request_server
string request_ip;
ulong request_port;
+ //scripting_and_scheduling
+ string python_path;
+ string scripts_dir;
//logs
string logs_dir;
string general_log_file;
@@ -129,6 +132,9 @@ class Tsettings{
//request_server
request_ip("127.0.0.1"),
request_port(10000),
+ //scripting_and_scheduling
+ python_path("/usr/bin/python"),
+ scripts_dir("./scripts"),
//logs
logs_dir("./logs"),
general_log_file("segget.log"),