#include #include #include #include #include #include #include #include #include #include #include #include typedef struct _Connection { socklen_t length; sockaddr_in addr; pthread_t threadIndex; int sockfd; } Connection; void startSession(int portNum); void *procUser(void *); int readBytes(int fd, void *ptr, size_t size); int writeBytes(int fd, void *ptr, size_t size); pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; std::vector ct; int main(int argc, char **argv) { signal(SIGPIPE, 0); if(argc != 2) { std::cout << "stp: port" << std::endl; return 0; } else { int port_num = atoi(argv[1]); if(port_num <= 0) { std::cerr << "Invalid Port Number" << std::endl; return EXIT_FAILURE; } startSession(port_num); } return EXIT_SUCCESS; } void startSession(int portNum) { int listen_fd; struct sockaddr_in address; bool active = true; listen_fd = socket(AF_INET,SOCK_STREAM, 0); memset((char*)&address, 0, sizeof(address)); address.sin_port = htons(portNum); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; int yup = 1; setsockopt(listen_fd, SOL_SOCKET,SO_REUSEADDR,(const char*)&yup,sizeof(yup)); bind(listen_fd, (struct sockaddr*)&address, sizeof(address)); listen(listen_fd, 5); std::cout << "Listening on port: " << portNum << "\n"; while( active == true ) { Connection connection; connection.sockfd = accept(listen_fd, (struct sockaddr *)&connection.addr, &connection.length); pthread_mutex_lock(&mutex); ct.push_back(connection); int pos = ct.size()-1; pthread_mutex_unlock(&mutex); pthread_create(&ct[pos].threadIndex, 0, procUser, (void*)&pos); sleep(10); } } void *procUser(void *index) { int offset = *(int*)index; std::cout << "Connected to [ Thread Index: " << offset << " ] " << std::endl; pthread_mutex_lock(&mutex); int rd_socket = ct[offset].sockfd; std::vector::iterator it = ct.begin() + offset; pthread_mutex_unlock(&mutex); char data[1024]; int len = read(rd_socket, (void*)data, sizeof(data)); data[len] = 0; char *token; token = strtok(data, " "); if(std::string(token) == "GET") { token = strtok(NULL, " "); char dir[1024]; char *d = getcwd(dir, 1024); std::string fname; fname += d; fname += token; std::cout << " * filename to send: " << fname << "\n"; std::fstream fobj; fobj.open(fname.c_str(), std::ios::in | std::ios::binary); if(fobj.is_open()) { fobj.seekg(0, std::ios::end); size_t len = fobj.tellg(); fobj.seekg(0, std::ios::beg); std::ostringstream ss; ss << "HTTP/1.1 200 OK\nDate: Sat 15 Aug 2009 00:00:00 GMT\nServer: STP 1.0\nAccept-Ranges: bytes\nContent-Length: " << len << "\nConnection: close\nContent-Type: application/zip\n\n"; int wr = writeBytes(rd_socket, (void*)ss.str().c_str(), ss.str().length()); int total_bytes = 0; int size = 1024; size_t total_size = len; while(!fobj.eof()) { static char wrBlock[1024]; memset(wrBlock, 0, 1024); fobj.read((char*)wrBlock, size); int wr = writeBytes(rd_socket, (void*)wrBlock, size); if(total_size <= size) size = total_size; else total_size -= size; } fobj.close(); std::cout << " * File Sent...\n"; close(rd_socket); } else { std::cout << "could not open source file: " << fname << "\n"; } } else { std::cout << "malformed get, instead I found " << token << "\n"; } pthread_mutex_lock(&mutex); ct.erase(it); pthread_mutex_unlock(&mutex); std::cout << "thread " << offset << " exited\n"; } int readBytes(int current_socket, void *data, size_t size) { size_t len = size; size_t total = 0; int cur_; char *cdata = (char*) data; while ((len != 0) && ((cur_ = recv(current_socket, cdata, len, 0)) > 0)) { if (cur_ == -1) { std::cerr << "mxsocket: error on read\n"; return -1; } len -= cur_; cdata += cur_; total += cur_; } return total; } int writeBytes(int current_socket, void *data, size_t size) { size_t len = size; size_t total = 0; int cur_; char *cdata = (char*) data; while ((len != 0) && ((cur_ = send(current_socket, cdata, len, 0)) != 0)) { if (cur_ == -1) { std::cerr << "mxsocket: error on write\n"; return -1; } len -= cur_; cdata += cur_; total += cur_; } return total; }