00001
00002
00003 #include "../include/repository.h"
00004 #include "../include/command.h"
00005 #include "../include/DFR_CL.h"
00006 #include "../include/cond_comp.h"
00007 #include <arpa/inet.h>
00008
00009 extern repository_class repository;
00010
00011
00012
00013 void serve_start_file_transfer (int req_sock, string file_name,
00014 string CL_address, list<string>* obtained_files, bool* error) {
00015 string s_address;
00016 int s_port;
00017 char buf[INT_AS_STRING_BYTES];
00018 int ret = repository.obtain_file(file_name, &s_address, &s_port, req_sock);
00019 switch(ret) {
00020 case 0:
00021 obtained_files->push_back(file_name);
00022 sprintf(buf, "%i", s_port);
00023 s_address = s_address + ':' + buf;
00024 LOG(printf("DFR as CL_req_s -> CL at %s obtained file: %s, server is %s\n",
00025 CL_address.c_str(), file_name.c_str(), s_address.c_str()));
00026 reply_command(req_sock, OK, s_address.length()+1, s_address.c_str());
00027 break;
00028 case 1:
00029 LOG(printf("DFR as CL_req_s -> CL at %s could not obtain file: %s, FSs are full\n",
00030 CL_address.c_str(), file_name.c_str()));
00031 reply_command(req_sock, ERR_TOO_MANY_CLIENTS, 0, NULL);
00032 break;
00033 case -1:
00034 LOG(printf("DFR as CL_req_s -> CL at %s could not obtain file: %s, file not found\n",
00035 CL_address.c_str(), file_name.c_str()));
00036 reply_command(req_sock, ERR_FILE_NOT_EXISTS, 0, NULL);
00037 break;
00038 default:
00039 LOG(printf("DFR as CL_req_s -> unknown error for client at %s\n",
00040 CL_address.c_str()));
00041 *error = true;
00042 }
00043 }
00044
00045 void serve_end_file_transfer (int req_sock, string file_name,
00046 string CL_address, list<string>* obtained_files, bool* error) {
00047 list<string>::iterator j;
00048 int ret = repository.release_file(file_name, req_sock);
00049 switch(ret) {
00050 case 0:
00051 for(j=obtained_files->begin(); j != obtained_files->end(); j++)
00052 if((*j)==file_name) {
00053 obtained_files->erase(j);
00054 break;
00055 }
00056 LOG(printf("DFR as CL_req_s -> CL at %s released file: %s\n",
00057 CL_address.c_str(), file_name.c_str()));
00058 reply_command(req_sock, OK, 0, NULL);
00059 break;
00060 case -1:
00061 LOG(printf("DFR as CL_req_s -> CL at %s could not release file: %s\n",
00062 CL_address.c_str(), file_name.c_str()));
00063 reply_command(req_sock, ERR_NO_TRANSFER, 0, NULL);
00064 break;
00065 default:
00066 LOG(printf("DFR as CL_req_s -> unknown error for client at %s\n",
00067 CL_address.c_str()));
00068 *error = true;
00069 }
00070 }
00071
00072 void serve_reg_notification (int req_sock, string file_name,
00073 string CL_address, list<string>* obtained_files, bool* error) {
00074 int ret, d_size;
00075 char* add_d;
00076 LOG(printf("DFR as CL_req_s -> CL at %s requested notification on file: %s\n",
00077 CL_address.c_str(), file_name.c_str()));
00078 reply_command(req_sock, OK, 0, NULL);
00079 repository.wait_file(file_name);
00080 LOG(printf("DFR as CL_req_s -> file %s is probably available for CL at %s\n",
00081 file_name.c_str(), CL_address.c_str()));
00082 command c(notify, file_name.c_str());
00083 ret = send_command(req_sock, c, &d_size, &add_d);
00084 delete(add_d);
00085 switch(ret) {
00086 case OK:
00087 serve_start_file_transfer(req_sock, file_name,
00088 CL_address, obtained_files, error);
00089 break;
00090 case ERR_NO_NOTIFICATION:
00091 break;
00092 default:
00093 LOG(printf("DFR as CL_req_s -> unknown error for client at %s\n",
00094 CL_address.c_str()));
00095 *error = true;
00096 }
00097 }
00098
00099 void* CL_req_s_body (void* sock) {
00100 pthread_detach(pthread_self());
00101 int req_sock = (int)sock;
00102 string CL_address;
00103 sockaddr_in CL_addr;
00104 socklen_t CL_addrlen = sizeof(CL_addr);
00105 command com;
00106 char buf1[INET_ADDRSTRLEN];
00107 char buf2[INT_AS_STRING_BYTES];
00108 bool error = false;
00109
00110 list<string> obtained_files;
00111 list<string>::iterator j;
00112 int ret = getpeername(req_sock, (sockaddr*)&CL_addr, &CL_addrlen);
00113 if(ret < 0) {
00114 LOG(printf("DFR as CL_req_s -> could not get CL address\n"));
00115 close(req_sock);
00116 pthread_exit(NULL);
00117 }
00118 CL_address = inet_ntop(AF_INET, &(CL_addr.sin_addr), buf1, INET_ADDRSTRLEN);
00119 int port = ntohs(CL_addr.sin_port);
00120 sprintf(buf2, "%i", port);
00121 CL_address += ':';
00122 CL_address += buf2;
00123 LOG(printf("DFR as CL_req_s -> CL at %s connected and ready\n", CL_address.c_str()));
00124 while(!error) {
00125 ret = receive_command(req_sock, &com);
00126 if(ret == -1)
00127 break;
00128 switch(com.id) {
00129 case start_file_transfer:
00130 serve_start_file_transfer(req_sock, com.file_name,
00131 CL_address, &obtained_files, &error);
00132 break;
00133 case end_file_transfer:
00134 serve_end_file_transfer(req_sock, com.file_name,
00135 CL_address, &obtained_files, &error);
00136 break;
00137 case reg_notification:
00138 serve_reg_notification(req_sock, com.file_name,
00139 CL_address, &obtained_files, &error);
00140 break;
00141 default:
00142 LOG(printf("DFR as CL_req_s -> received invalid command from CL at %s\nDFR as CL_req_s -> the CL will be disconnected\n",
00143 CL_address.c_str()));
00144 error = true;
00145 }
00146 }
00147 for(j=obtained_files.begin(); j != obtained_files.end(); j++)
00148 repository.release_file(*j, req_sock);
00149 LOG(printf("DFR as CL_req_s -> CL at %s disconnected\n", CL_address.c_str()));
00150 close(req_sock);
00151 pthread_exit(NULL);
00152 }
00153
00154 void* CL_s_body (void* sock) {
00155 int l_sock = (int)sock, ret;
00156 int cur_sock, err_counter = 0;
00157 sockaddr_in CL_addr;
00158 socklen_t CL_addrlen = sizeof(CL_addr);
00159 pthread_t CL_req_s;
00160 while(1) {
00161 cur_sock = accept(l_sock, (sockaddr*)&CL_addr, &CL_addrlen);
00162 if(cur_sock < 0) {
00163 LOG(printf("DFR as CL_s -> could not accept a CL\n"));
00164 err_counter++;
00165 if(err_counter >= MAX_ERR_COUNT_CL)
00166 pthread_exit(NULL);
00167 else continue;
00168 }
00169 ret = pthread_create(&CL_req_s, 0, CL_req_s_body, (void*)cur_sock);
00170 if(ret != 0) {
00171 LOG(printf("DFR as CL_s -> could not create a request server thread\n"));
00172 pthread_exit(NULL);
00173 }
00174 }
00175 pthread_exit(NULL);
00176 }