DocumentationGenerated on Thu Aug 31 00:02:28 2006 |
||
Data.cppGo to the documentation of this file.00001 00002 // $Id: Data.cpp,v 1.13 2005/08/23 19:32:31 klas Exp $ 00003 // 00004 // Usage: Data class. inherited from Connection, everything pertaining to 00005 // data connection goes here. 00006 // 00007 // A part of babyftpd, licensed under the GNU GPL, see the file 00008 // LICENSE for complete information. 00010 00011 #define DATA_CPP 00012 #define NETINCLS 00013 #define BABY_CORE 00014 #include "Data.h" 00015 00016 Data::Data(User *user, int file_id, string file_name, int trans_type) 00017 : Connection() 00018 { 00019 this->thread_id(0); // data_wrapper sets this to it's own. 00020 this->_file_id = file_id; 00021 this->_file_name = file_name; 00022 this->user = user; 00023 this->_settings = user->settings(); 00024 this->addr(user->data_addr()); 00025 struct timeval tv = {1, 0}; 00026 this->timeout(tv); 00027 if(trans_type == 1) 00028 this->settings(RETR_TRANS, B_SET); 00029 00030 this->settings(DATA_OPEN, B_SET); 00031 #ifdef USE_TLS 00032 this->settings(TLS_INITED, B_RESET); 00033 this->settings(TLS_ENABLED, B_RESET); 00034 #endif // USE_TLS 00035 00036 if(this->settings(PASSIVE)) 00037 this->open_passive(); 00038 else // ACTIVE 00039 this->open_active(); 00040 00041 // if the data connection comes from another host than the 00042 // ctrl connection we drop it.. unless the user is tls protected. 00043 if(this->addr().sin_addr.s_addr != user->addr().sin_addr.s_addr) 00044 { 00045 #ifdef USE_TLS 00046 if(!user->settings(TLS_ENABLED)) 00047 { 00048 #endif // USE_TLS 00049 close(this->socket_id()); 00050 this->settings(DATA_OPEN, B_RESET); 00051 } 00052 #ifdef USE_TLS 00053 } 00054 #endif //USE_TLS 00055 } 00056 00057 void Data::open_passive() 00058 { 00059 socklen_t len = sizeof(this->addr()); 00060 struct sockaddr_in temp_addr = this->addr(); 00061 00062 fd_set acc_set; 00063 FD_ZERO(&acc_set); 00064 FD_SET(user->data_id(), &acc_set); 00065 struct timeval tv = this->timeout(); 00066 00067 if(select(user->data_id() + 1, &acc_set, NULL, NULL, &tv) > 0) 00068 { 00069 int ret = accept(user->data_id(), 00070 reinterpret_cast<struct sockaddr*>(&temp_addr), &len); 00071 this->socket_id(ret); 00072 this->addr(temp_addr); 00073 } 00074 else 00075 this->settings(DATA_OPEN, B_RESET); 00076 00077 close(user->data_id()); 00078 } 00079 00080 void Data::open_active() 00081 { 00082 this->socket_id(socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)); 00083 00084 int on = 1; 00085 setsockopt(this->socket_id(), SOL_SOCKET, SO_REUSEADDR, 00086 (static_cast<void*>(&on)), sizeof(on)); 00087 struct sockaddr_in my_addr; 00088 my_addr.sin_port = htons(config->general.data_port); 00089 my_addr.sin_addr.s_addr = htonl(INADDR_ANY); 00090 00091 uid_t old_uid = 0; 00092 // if dataport is below 1024 we need root. 00093 if(config->general.data_port <= 1024) 00094 { 00095 old_uid = geteuid(); 00096 seteuid(0); 00097 } 00098 int ret = bind(this->socket_id(), reinterpret_cast<struct sockaddr*> 00099 (&my_addr), sizeof(my_addr)); 00100 if(config->general.data_port <= 1024) 00101 seteuid(old_uid); 00102 00103 if(ret != 0) 00104 logging->log_this(3, TYPE_INFO, 00105 "Failed to bind to data port " + util.itos(config->general.data_port) 00106 + ", falling back to arbitrary port."); 00107 00108 struct sockaddr_in tmp_addr = this->addr(); 00109 00110 // go into nonblocking 00111 long sock_arg = fcntl(this->socket_id(), F_GETFL, NULL); 00112 sock_arg |= O_NONBLOCK; 00113 fcntl(this->socket_id(), F_SETFL, sock_arg); 00114 00115 int sock_err = connect(this->socket_id(), reinterpret_cast<struct sockaddr*> 00116 (&tmp_addr), sizeof(tmp_addr)); 00117 this->addr(tmp_addr); 00118 00119 if(sock_err < 0) 00120 if(errno == EINPROGRESS) 00121 { 00122 struct timeval tv = this->timeout(); 00123 fd_set con_set; 00124 FD_ZERO(&con_set); 00125 FD_SET(this->socket_id(), &con_set); 00126 if(select(this->socket_id() + 1, NULL, &con_set, NULL, &tv) < 0) 00127 this->settings(DATA_OPEN, B_RESET); 00128 } 00129 else 00130 this->settings(DATA_OPEN, B_RESET); 00131 00132 // leave non blocking 00133 long sock_arg2 = fcntl(this->socket_id(), F_GETFL, NULL); 00134 sock_arg2 &= (~O_NONBLOCK); 00135 fcntl(this->socket_id(), F_SETFL, sock_arg2); 00136 } 00137 00138 Data::~Data() 00139 { 00140 if(this->_file_id != -1) 00141 close(this->_file_id); 00142 00143 this->user->transfered( 00144 this->user->transfered() + this->transfered()); 00145 00146 if(this->thread_id()) 00147 { 00148 BABY_WRLOCK(user->lock); 00149 user->data_vec.erase(user->get_data_it(this->thread_id())); 00150 BABY_UNLOCK(user->lock); 00151 logging->log_this(4, TYPE_INFO, "data thread " + 00152 util.itos(this->thread_id()) + 00153 " exiting. Remaining data connections for " + user->user_name() + 00154 " is: " + util.itos(user->data_vec.size())); 00155 } 00156 } 00157 00158 void kill_data(void *data) 00159 { 00160 delete static_cast<Data*>(data); 00161 } |
- Copyright © 2005, BabyFTPd
- Powered by: