diff options
| author | Paul Buetow <paul@buetow.org> | 2010-11-21 16:20:55 +0000 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2010-11-21 16:20:55 +0000 |
| commit | 6fde6b0fe90abde84011202edd40fe46eb06af44 (patch) | |
| tree | ef760338c50b4df3ae9cca96347bca962fdbec7e /src/sock | |
| parent | 55b08bd93257d32df76efc4e8e3f49311c39ee82 (diff) | |
Diffstat (limited to 'src/sock')
| -rw-r--r-- | src/sock/context.cpp | 62 | ||||
| -rw-r--r-- | src/sock/context.h | 57 | ||||
| -rw-r--r-- | src/sock/sock.cpp | 661 | ||||
| -rw-r--r-- | src/sock/sock.h | 95 | ||||
| -rw-r--r-- | src/sock/sslsock.cpp | 17 | ||||
| -rw-r--r-- | src/sock/sslsock.h | 4 |
6 files changed, 433 insertions, 463 deletions
diff --git a/src/sock/context.cpp b/src/sock/context.cpp deleted file mode 100644 index be46a07..0000000 --- a/src/sock/context.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/*:* - *: File: ./src/sock/context.cpp - *: - *: yChat; Homepage: ychat.buetow.org; Version 0.9.0-CURRENT - *: - *: Copyright (C) 2003 Paul C. Buetow, Volker Richter - *: Copyright (C) 2004 Paul C. Buetow - *: Copyright (C) 2005 EXA Digital Solutions GbR - *: Copyright (C) 2006, 2007 Paul C. Buetow - *: - *: This program is free software; you can redistribute it and/or - *: modify it under the terms of the GNU General Public License - *: as published by the Free Software Foundation; either version 2 - *: of the License, or (at your option) any later version. - *: - *: This program 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 General Public License for more details. - *: - *: You should have received a copy of the GNU General Public License - *: along with this program; if not, write to the Free Software - *: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *:*/ - -#ifndef CONTEXT_CPP -#define CONTEXT_CPP - -#include "context.h" - -using namespace std; - -context::context(sock *p_sock, struct event *p_event, int i_fd) -{ - this->p_sock = p_sock; - this->p_event = p_event; - this->i_fd = i_fd; -} - -context::~context() -{ - shutdown(i_fd, 2); - close(i_fd); - - if (this->p_event) - delete this->p_event; - - if (this->p_map_params) - delete this->p_map_params; - - if (this->p_response) - delete this->p_response; -} - -void -context::del_event() -{ - if (this->p_event) - delete this->p_event; - this->p_event = NULL; -} -#endif diff --git a/src/sock/context.h b/src/sock/context.h deleted file mode 100644 index a604cda..0000000 --- a/src/sock/context.h +++ /dev/null @@ -1,57 +0,0 @@ -/*:* - *: File: ./src/sock/context.h - *: - *: yChat; Homepage: ychat.buetow.org; Version 0.9.0-CURRENT - *: - *: Copyright (C) 2003 Paul C. Buetow, Volker Richter - *: Copyright (C) 2004 Paul C. Buetow - *: Copyright (C) 2005 EXA Digital Solutions GbR - *: Copyright (C) 2006, 2007 Paul C. Buetow - *: - *: This program is free software; you can redistribute it and/or - *: modify it under the terms of the GNU General Public License - *: as published by the Free Software Foundation; either version 2 - *: of the License, or (at your option) any later version. - *: - *: This program 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 General Public License for more details. - *: - *: You should have received a copy of the GNU General Public License - *: along with this program; if not, write to the Free Software - *: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - *:*/ - -#include "../incl.h" - -#ifndef CONTEXT_H -#define CONTEXT_H - -#include <map> -#include <string> -#include <sys/time.h> -#include <event.h> - -using namespace std; - -class sock; -class user; - -struct context -{ - sock *p_sock; - struct event* p_event; - char c_buf[READSOCK+1]; - //string s_request; - map<string,string> *p_map_params; - int i_fd; - string *p_response; - user *p_user; - - context(sock *p_sock, struct event *p_event, int i_fd); - ~context(); - void del_event(); -}; - -#endif diff --git a/src/sock/sock.cpp b/src/sock/sock.cpp index fdba716..45583e3 100644 --- a/src/sock/sock.cpp +++ b/src/sock/sock.cpp @@ -1,12 +1,11 @@ /*:* *: File: ./src/sock/sock.cpp *: - *: yChat; Homepage: ychat.buetow.org; Version 0.9.0-CURRENT + *: yChat; Homepage: www.yChat.org; Version 0.8.3-CURRENT *: *: Copyright (C) 2003 Paul C. Buetow, Volker Richter *: Copyright (C) 2004 Paul C. Buetow *: Copyright (C) 2005 EXA Digital Solutions GbR - *: Copyright (C) 2006, 2007 Paul C. Buetow *: *: This program is free software; you can redistribute it and/or *: modify it under the terms of the GNU General Public License @@ -30,48 +29,116 @@ #include <errno.h> #include <sys/types.h> #include <unistd.h> -#include <fcntl.h> #include "sock.h" -#include "../tool/tool.h" using namespace std; -vector< sock* > sock::vec_socks; -int sock::i_id_counter = 0; - sock::sock() { - this->i_id = ++i_id_counter; - this->b_run = true; this->i_req = 0; - this->p_reqp = new reqp(); + this->req_parser = new reqp(); #ifdef LOGGING - this->log_daemon = new logd( wrap::CONF->get_elem( "httpd.logging.accessfile" ), + this->log_daemon = new logd( wrap::CONF->get_elem( "httpd.logging.accessfile" ), wrap::CONF->get_elem( "httpd.logging.access_lines" ) ); #endif - this->p_ip_cache_map = new shashmap < string, unsigned, self_hash<unsigned>, equals_allocator<unsigned> >; - vec_socks.push_back(this); + this->ip_cache_map = new shashmap + < string, unsigned, self_hash<unsigned>, equals_allocator<unsigned> >; +} + +int +sock::_send(_socket *p_sock, const char *sz, int len) +{ +#ifdef OPENSSL + return send(p_sock->i_sock, sz, len, 0); +#else + return send(*p_sock, sz, len, 0); +#endif +} + +int +sock::_read(_socket *p_sock, char *sz, int len) +{ +#ifdef OPENSSL + return read(p_sock->i_sock, sz, len); +#else + return read(*p_sock, sz, len); +#endif +} + +int +sock::_close(_socket *p_sock) +{ +#ifdef OPENSSL + shutdown( p_sock->i_sock, 2 ); + close ( p_sock->i_sock ); +#else + shutdown( *p_sock, 2 ); + close ( *p_sock ); +#endif + delete p_sock; } //<<* -/* void -sock::chat_stream(context *p_context, string s_msg) +sock::chat_stream( _socket *p_sock, user *p_user, map<string,string> &map_params ) { - p_user->set_context(p_sock); + string s_msg( "\n" ); + + for ( int i = 0; i < PUSHSTR; i++ ) + _send(p_sock,s_msg.c_str(), s_msg.size()); - _send(p_sock, s_msg.c_str(), s_msg.size()); // FOOBAR + pthread_mutex_t mutex; + pthread_mutex_init( &mutex, NULL ); + pthread_mutex_lock( &mutex ); - for (int i = 0; i < PUSHSTR; ++i) - _send(p_sock, " \n", 2); + do + { + s_msg = p_user->get_mess( ); - p_user->set_sock(p_sock); + if ( 0 > _send( p_sock, s_msg.c_str(), s_msg.size() ) ) + { + p_user->set_online( false ); + break; + } + + pthread_cond_wait( &(p_user->cond_message), &mutex ); + } + while( p_user->get_online() ); + + pthread_mutex_destroy( &mutex ); + + // if there is still a message to send: + s_msg = p_user->get_mess( ); + + if ( ! s_msg.empty() ) + _send( p_sock, s_msg.c_str(), s_msg.size()); + + // remove the user from its room. + string s_user( p_user->get_name() ); + string s_user_lowercase( p_user->get_lowercase_name() ); + + room* p_room = p_user->get_room(); + p_room->del_elem( s_user_lowercase ); + + // post the room that the user has left the chat. + s_msg = wrap::TIMR->get_time() + " " + + p_user->get_colored_bold_name() + + wrap::CONF->get_elem( "chat.msgs.userleaveschat" ) + + "<br>\n"; + + p_room->msg_post( &s_msg ); + p_room->reload_onlineframe(); + +#ifdef VERBOSE + cout << REMUSER << s_user << endl; +#endif + + wrap::GCOL->add_user_to_garbage( p_user ); } -*/ //*>> int @@ -81,366 +148,402 @@ sock::_make_server_socket( int i_port ) struct sockaddr_in name; // create the server socket. - i_sock = socket (AF_INET, SOCK_STREAM, 0); - // i_sock = socket (PF_INET, SOCK_STREAM, 0); + i_sock = socket (PF_INET, SOCK_STREAM, 0); if (i_sock < 0) { - wrap::system_message(SOCKERR, errno); + wrap::system_message( SOCKERR ); if ( ++i_port > MAXPORT ) exit(1); - wrap::system_message(SOCKERR, errno); + wrap::system_message( SOCKERR ); return _make_server_socket( i_port ); } // give the server socket a name. name.sin_family = AF_INET; - name.sin_addr.s_addr = htonl(INADDR_ANY); name.sin_port = htons(i_port); + name.sin_addr.s_addr = htonl(INADDR_ANY); int i_optval = 1; - if (bind(i_sock, (struct sockaddr *) &name, sizeof (name)) < 0) + setsockopt( i_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&i_optval, sizeof(int) ); + + if ( bind(i_sock, (struct sockaddr *) &name, sizeof (name)) < 0 ) { - wrap::system_message(BINDERR, errno); + wrap::system_message( BINDERR ); - if (++i_port > MAXPORT) + if ( ++i_port > MAXPORT ) exit(1); - wrap::system_message(string(SOCKERR) + tool::int2string(i_port)); + wrap::system_message( string(SOCKERR) + tool::int2string(i_port) ); - // Re-run recursive. - return _make_server_socket(i_port); - } - - setsockopt(i_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&i_optval, sizeof(int)); - - if (set_nonblock(i_server_sock) < 0) - { - wrap::system_message(NONBLER, errno); - exit(EXIT_FAILURE); + // Rerun recursive. + return _make_server_socket( i_port ); } - wrap::system_message(SOCKCRT + string("localhost:") + tool::int2string(i_port)); + wrap::system_message( SOCKCRT + string("localhost:") + tool::int2string(i_port) ); i_server_port = i_port; i_server_sock = i_sock; - if (listen(i_sock, BACKLOG) < 0) - { - wrap::system_message(LISTERR, errno); - exit(EXIT_FAILURE); - } - - wrap::system_message(SOCKRDY); return i_sock; } -#ifdef OPENSSL -// This method is virtual, and is overloaded by sslsock! -bool -sock::_main_loop_do_ssl_stuff(int &i_new_sock) +string +sock::read_http_line(_socket *p_sock) { - return 0; -} -#endif + string s_line; + int i_total = 0; + int i_read = 0; + char ch; -void -sock::process_request() -{ - int i; - struct sockaddr_in clientname; - socklen_t size; - - ++i_req; - int i_client_sock = accept(i_server_sock, (struct sockaddr *) &clientname, &size); - - if (i_client_sock == -1) + do { - switch (errno) - { - case EAGAIN: - case EINTR: - return; - } - } + i_read = _read(p_sock, &ch, sizeof(char)); - if (0 < set_nonblock(i_client_sock)) - { - wrap::system_message(NONBCER, errno); - } - -#ifdef OPENSSL - _main_loop_do_ssl_stuff(i_client_sock); -#endif + if(i_read <= 0) + return ""; -#ifdef VERBOSE - wrap::system_message(NEWREQU - + tool::int2string(i_req) + " " - + string(inet_ntoa( clientname.sin_addr )) + ":" - + tool::int2string(ntohs ( clientname.sin_port )) - + " @" + tool::int2string(get_id()) - ); -#endif + s_line += ch; + i_total++; + } + while((ch != '\n') && i_total < MAXLENGTH); - context *p_context = new context(this, new struct event, i_client_sock); + if(ch != '\n') + /* + ** the games people play + */ + return ""; - event_set(p_context->p_event, i_client_sock, EV_READ , handle_client_read, p_context); - event_add(p_context->p_event, NULL); + return s_line; } - -void -sock::clean_ipcache() +int +sock::read_http(_socket *p_sock, char *c_zbuf, int &i_postpayloadoffset) { - int i_ipcachesize = wrap::CONF->get_int("httpd.ipcachesize"); - int i_currentsize = p_ip_cache_map->size(); - - if (i_currentsize > 0 && (i_ipcachesize == 0 || i_ipcachesize <= i_currentsize)) - wrap::system_message(SOCKCA2+tool::int2string(i_currentsize)+","+tool::int2string(i_ipcachesize)+")"); -} + /* + ** 1) Read the first line + ** 2) If GET, handle as such + ** 3) If POST, handle as such + */ + char ch; + int i_read; + int i_ret = -1; + int x,z; + + string s_content_length; + string s_cl; + string s_post_return; + string s_line = read_http_line(p_sock); + + i_postpayloadoffset = 0; + if(s_line.empty()) { + wrap::system_message(SOCKER4); + return -1; + } -void -sock::init_event_handlers() -{ - for (vector< sock* >::iterator iter = sock::vec_socks.begin(); - iter != sock::vec_socks.end(); ++iter) + /* + ** GET yada\r\n Followed by stuff we don't care about :) heh. + ** 01234 + */ + /* + ** POST yada\r\n + ** xxxxx + ** Content-Length: NNN\n + ** \n + */ + if(s_line.substr(0, 3) == "GET") { - wrap::system_message(EVENTSO, (*iter)->get_id()); - (*iter)->init_server_event_handler(); + if(s_line.length() > READSOCK) + /* + ** Buffer overflow + */ + s_line = s_line.substr(0, READSOCK); + + memcpy(c_zbuf,s_line.c_str(),s_line.length()); + return s_line.length(); } -} -void -sock::init_server_event_handler() -{ - event_set(&ev_handle_server_accept, i_server_sock, EV_READ | EV_PERSIST, handle_server_accept, this); - event_add(&ev_handle_server_accept, NULL); -} - -void -sock::handle_server_accept(int i_fd, short event, void *p_arg) -{ - sock *p_sock = static_cast<sock*>(p_arg); - p_sock->process_request(); -} + else + { + /* + ** POST yada + ** 01234 + */ + if(s_line.substr(0, 4) != "POST") { + wrap::system_message(SOCKER4); + return -1; + } -void -sock::handle_client_read(int i_fd, short event, void *p_arg) -{ - static int i_size = READSOCK * sizeof(char); - context *p_context = static_cast<context*>(p_arg); + /* + ** Get us to the Content-Length: + */ + s_post_return += s_line; + i_postpayloadoffset += s_line.length(); - if (-1 == read(i_fd, p_context->c_buf, i_size)) - { - switch (errno) + for(x =0; x < MAXLINES; ++x) { - case EAGAIN: - case EINTR: - event_add(p_context->p_event, NULL); - return; + s_line = read_http_line(p_sock); + s_post_return += s_line; + i_postpayloadoffset += s_line.length(); + + if (s_line.compare(0, 15, "Content-Length:")) + continue; + + // Match found on Content-Length:... process, and then break out and get us to the promised land + s_content_length = s_line.substr( 16 /*strlen("Content-Length: ")*/, + s_line.length() - 16 /*strlen("Content-Length: ")*/); + + /* + ** Content-Length: 333\n + ** 0123456789abcdefghijklmnopqrstuvwxyzAB + */ + z = 0; + + do + { + ch = s_content_length[z]; + if(isdigit(ch)) + s_cl += ch; + + ++z; + } + while(ch != '\n'); + + break; } - } - p_context->del_event(); - string s_buf(p_context->c_buf); - string s_query(""); - - bool b_is_post_request; + if(s_cl.empty()) { + wrap::system_message(SOCKER4); + return -1; + } - if (strncmp("POST", p_context->c_buf, 4) == 0) - { - b_is_post_request = true;; + z = atoi(s_cl.c_str()); - int i_pos = s_buf.find(" HTTP", 0) + 1; + /* + ** If we are going to overflow the buffer just by the payload, leave + ** of, if z did not convert correctly. (should have been ok by isdigit) + */ + if(z > READSOCK || z < 0) { + wrap::system_message(SOCKER4); + return -1; + } - if (i_pos == string::npos && i_pos <= 5) + /* + ** We have MAXLINES to get to the blank line separating POST data. + */ + for(x = 0; x < MAXLINES; ++x) { - wrap::system_message(HTTPERR); - delete p_context; - return; - } + s_line = read_http_line(p_sock); + s_post_return += s_line; - s_query.append(s_buf.substr(5, i_pos - 5)); - } + i_postpayloadoffset += s_line.length(); + if(s_line == "\r\n") + break; + } - else if (strncmp("GET", p_context->c_buf, 3) == 0) - { - b_is_post_request = false; - int i_pos = s_buf.find(" HTTP", 0) + 1; + /* + ** funny business + */ + if(x == MAXLINES) { + wrap::system_message(SOCKER4); + return -1; + } - if (i_pos == string::npos && i_pos <= 5) + for(x = 0; x < z; ++x) { - wrap::system_message(HTTPERR); - delete p_context; - return; + if(_read(p_sock,&ch,sizeof(ch)) != 1) { + wrap::system_message(SOCKER4); + return -1; + } + + s_post_return += ch; } - s_query.append(s_buf.substr(5, i_pos - 5)); - } + if(s_post_return.length() > READSOCK) { + wrap::system_message(SOCKER4); + return -1; + } - // Invalid request - else - { - wrap::system_message(HTTPERR); - delete p_context; - return; + memcpy(c_zbuf,s_post_return.c_str(),s_post_return.length()); + return s_post_return.length(); } +} - // Remove /.. from the query - int i_pos, i_pos2; - while ( (i_pos = s_query.find("/..")) != string::npos ) - s_query.replace(i_pos, 3, "/"); - - sock *p_sock = p_context->p_sock; - - p_context->p_map_params = new map<string, string>; - map<string, string>& map_params = *p_context->p_map_params; +int +sock::read_write(_socket* p_sock) +{ + int i_postpayloadoffset; - struct sockaddr_in client; - static socklen_t client_size = sizeof(client); - getpeername(i_fd, (struct sockaddr *) &client, &client_size); +#ifdef OPENSSL + int i_sock = p_sock->i_sock; +#else + int i_sock = *p_sock; +#endif - shashmap< string, unsigned, self_hash<unsigned>, equals_allocator<unsigned> > *p_ip_cache_map - = p_sock->get_ip_cache_map(); + char c_req[READSOCK+1]; + memset(c_req, 0, sizeof(c_req)); - unsigned &i_addr = client.sin_addr.s_addr; + int i_bytes = read_http(p_sock, c_req, i_postpayloadoffset); - if ( (map_params["REMOTE_ADDR"] = p_ip_cache_map->get_elem(i_addr)) == "" ) + if (i_bytes <= 0) { - map_params["REMOTE_ADDR"] = string(inet_ntoa(client.sin_addr)); - p_ip_cache_map->set_elem(map_params["REMOTE_ADDR"], i_addr); - wrap::system_message(SOCKCAC+map_params["REMOTE_ADDR"]); + wrap::system_message( READERR ); + } - // Get HTTP Header values - i_pos = s_buf.find("\n"); - if (i_pos != string::npos) + else { - map_params["QUERY_STRING"] = tool::trim(s_buf.substr(0,i_pos-1)); + // stores the request params. + map<string,string> map_params; - do - { - string s_line(s_buf.substr(0, i_pos)); - i_pos2 = s_line.find(":"); - - if (i_pos2 != string::npos && s_line.length() > i_pos2+1) - map_params[ tool::trim(s_line.substr(0, i_pos2)) ] = tool::trim(s_line.substr(i_pos2+1)); + // get the s_rep ( s_html response which will be send imediatly to the client + struct sockaddr_in client; + size_t size = sizeof(client); - s_buf = s_buf.substr(s_line.size() + 1); - i_pos = s_buf.find("\n"); + getpeername(i_sock, (struct sockaddr *)&client, &size); + unsigned &s_addr = client.sin_addr.s_addr; + if ( (map_params["REMOTE_ADDR"] = ip_cache_map->get_elem(s_addr)) == "" ) + { + map_params["REMOTE_ADDR"] = string(inet_ntoa(client.sin_addr)); + ip_cache_map->set_elem(map_params["REMOTE_ADDR"], s_addr); + wrap::system_message(SOCKCAC+map_params["REMOTE_ADDR"]); } - while (i_pos != string::npos); - } - // Get request string parameters - string s_parameters = tool::url_decode(s_query); - string s_tmp, s_request(""); + string s_rep = req_parser->parse(p_sock, string(c_req), map_params, i_postpayloadoffset); - if ( (i_pos = s_parameters.find("?")) != string::npos) - { - s_request.append(s_parameters.substr(0, i_pos)); - s_parameters = s_parameters.substr(i_pos+1); - } +#ifdef LOGGING + log_daemon->log_access(map_params); +#endif - else if ( (i_pos = s_parameters.find(" ")) != string::npos) - { - s_request.append(s_parameters.substr(0, i_pos)); - } + // send s_rep to the client. + _send(p_sock, s_rep.c_str(), s_rep.size()); - else - { - s_request.append(s_parameters); - } + // dont need those vals anymore. + map_params.clear(); - if (b_is_post_request) - s_parameters = s_buf; + _close(p_sock); + return 0; + } - while ( (i_pos = s_parameters.find("&")) != string::npos ) - { - s_tmp = s_parameters.substr(0, i_pos ); + _close(p_sock); + return 1; +} - if ( (i_pos2 = s_tmp.find("=")) != string::npos ) - map_params[ s_tmp.substr(0, i_pos2) ] = tool::replace( s_tmp.substr( i_pos2+1 ), "\\AND", "&"); +void +sock::_main_loop_init() +{ + wrap::system_message(SOCKUNS); +} - s_parameters = s_parameters.substr(i_pos+1); - } +#ifdef OPENSSL +// This method is virtual, and is overloaded by sslsock! +bool +sock::_main_loop_do_ssl_stuff(int &i_new_sock) +{ + return 0; +} +#endif - // Get the last request parameter, which does not have a "&" on the end! - if ( (i_pos = s_parameters.find("=")) != string::npos ) - { - if ( (i_pos2 = s_parameters.find(" ")) != string::npos ) - map_params[ s_parameters.substr(0, i_pos) ] = s_parameters.substr(i_pos+1, i_pos2-i_pos-1); - else - map_params[ s_parameters.substr(0, i_pos) ] = s_parameters.substr(i_pos+1); - } +_socket* +sock::_create_container(int &i_sock) +{ + _socket* p_sock = new _socket; -#ifdef VERBOSE - wrap::system_message(REQUEST + s_request); +#ifdef OPENSSL + p_sock->i_sock = i_sock; +#else + *p_sock = i_sock; #endif + return p_sock; +} - if (s_request.empty()) - s_request = wrap::CONF->get_elem("httpd.startsite"); +int +sock::start() +{ + wrap::system_message( SOCKSRV ); + int i_sock = i_server_sock; - map_params["request"] = s_request; + int i_port = tool::string2int( wrap::CONF->get_elem("httpd.serverport") ); + _main_loop_init(); + int i; + fd_set active_fd_set, read_fd_set; + struct sockaddr_in clientname; + size_t size; + + if (listen (i_sock, 1) < 0) { - string s_ext(tool::get_extension(s_request)); + wrap::system_message( LISTERR ); + exit( EXIT_FAILURE ); + } - if ( s_ext == "" ) - s_ext = "default"; + wrap::system_message( SOCKRDY ); - map_params["content-type"] = wrap::CONF->get_elem( "httpd.contenttypes." + s_ext ); - } + // initialize the set of active sockets. + FD_ZERO (&active_fd_set); + FD_SET (i_sock, &active_fd_set); -//#ifdef VERBOSE -// for (map<string, string>::iterator i = map_params.begin(); i != map_params.end(); ++i) -// cout << "=>" << i->first << "=" << i->second << "<=" << endl; -//#endif + while(b_run) + { + // block until input arrives on one or more active sockets. + read_fd_set = active_fd_set; + if (select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) + { + wrap::system_message( SELCERR ); + exit(EXIT_FAILURE); + } - p_context->p_response = new string(""); - p_sock->get_req_parser()->parse(p_context); + // service all the sockets with input pending. + for (i = 0; i < FD_SETSIZE; ++i) + if (FD_ISSET(i, &read_fd_set)) + { + if (i == i_sock) + { + ++i_req; // connection request on original socket. - struct event *p_ev_handle_client_write = new struct event; - p_context->p_event = p_ev_handle_client_write; + int i_new_sock; + size = sizeof(clientname); + i_new_sock = accept(i_sock, (struct sockaddr *) &clientname, &size); - event_set(p_ev_handle_client_write, i_fd, EV_WRITE, handle_client_write, p_context); - event_add(p_ev_handle_client_write, NULL); -} +#ifdef OPENSSL + if (_main_loop_do_ssl_stuff(i_new_sock)) + continue; +#endif -void -sock::handle_client_write(int i_fd, short event, void *p_arg) -{ - static int i_char_size = sizeof(char); +#ifdef VERBOSE + wrap::system_message(NEWREQU + + tool::int2string(i_req) + " " + + string(inet_ntoa( clientname.sin_addr )) + ":" + + tool::int2string(ntohs ( clientname.sin_port )) + ); +#endif - context *p_context = static_cast<context*>(p_arg); - string *p_response = p_context->p_response; + FD_SET(i_new_sock, &active_fd_set); - if (-1 == write(i_fd, p_response->c_str(), p_response->length()*i_char_size)) - { - switch (errno) - { - case EAGAIN: - case EINTR: - event_add(p_context->p_event, NULL); - return; - } + } + else + { + _socket *p_sock = _create_container(i); + pool::run( (void*) p_sock ); + FD_CLR( i, &active_fd_set ); + } + } } - - delete p_context; } -int -sock::set_nonblock(int i_sock) +void +sock::clean_ipcache() { - if (fcntl(i_sock, F_SETFL, O_NONBLOCK) < 0) + int i_ipcachesize = wrap::CONF->get_int("httpd.ipcachesize"); + int i_currentsize = ip_cache_map->size(); + + if ( i_currentsize > 0 && (i_ipcachesize == 0 || i_ipcachesize <= i_currentsize) ) { - wrap::system_message(SOCKER5, errno); - return -1; + wrap::system_message( + SOCKCA2+tool::int2string(i_currentsize)+","+tool::int2string(i_ipcachesize)+")"); } - - return 0; } #endif diff --git a/src/sock/sock.h b/src/sock/sock.h index b09afb1..5b8db2f 100644 --- a/src/sock/sock.h +++ b/src/sock/sock.h @@ -1,12 +1,11 @@ /*:* *: File: ./src/sock/sock.h *: - *: yChat; Homepage: ychat.buetow.org; Version 0.9.0-CURRENT + *: yChat; Homepage: www.yChat.org; Version 0.8.3-CURRENT *: *: Copyright (C) 2003 Paul C. Buetow, Volker Richter *: Copyright (C) 2004 Paul C. Buetow *: Copyright (C) 2005 EXA Digital Solutions GbR - *: Copyright (C) 2006, 2007 Paul C. Buetow *: *: This program is free software; you can redistribute it and/or *: modify it under the terms of the GNU General Public License @@ -28,94 +27,76 @@ #ifndef SOCK_H #define SOCK_H -#include <vector> #include <queue> #include <netdb.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include "../reqp.h" #include "../chat/user.h" + +#include "../thrd/pool.h" #include "../maps/shashmap.h" #ifdef LOGGING #include "../logd.h" #endif -#include <sys/time.h> -#include <event.h> - using namespace std; -class sock +class sock { -private: - static vector< sock* > vec_socks; - static int i_id_counter; - long i_id; - protected: #ifdef LOGGING + logd *log_daemon; // the log daemon #endif - shashmap< string, unsigned, self_hash<unsigned>, equals_allocator<unsigned> > *p_ip_cache_map; + shashmap< string, unsigned, self_hash<unsigned>, equals_allocator<unsigned> > *ip_cache_map; int i_server_sock; int i_server_port; - unsigned long long i_req; // total number of server requests. - bool b_run; // true while socket manager is running. - reqp *p_reqp; // parses the http requests from clients. - struct event ev_handle_server_accept; - static void handle_server_accept(int i_fd, short event, void *p_arg); - static void handle_client_read(int i_fd, short event, void *p_arg); - static void handle_client_write(int i_fd, short event, void *p_arg); - static void handle_client_stream_write(int i_fd, short event, void *p_arg); + unsigned long long i_req; // total number of server requests. + bool b_run; // true while socket manager is running. + reqp *req_parser; // parses the http requests from clients. + char *c_buffer; // char buffer! + pthread_mutex_t mut_hits; - int set_nonblock(int i_sock); + static string inet_ntoa_callback(void* p_void); public: - explicit sock(); - void process_request(); - - shashmap< string, unsigned, self_hash<unsigned>, equals_allocator<unsigned> > * get_ip_cache_map() - { - return p_ip_cache_map; - } - reqp *get_req_parser() const - { - return p_reqp; - } - int get_id() const - { - return i_id; - } - string dump() - { - return p_ip_cache_map->dump(); - } - bool get_server_() const - { - return b_run; - } - bool get_run() const - { - return b_run; - } - bool set_run( bool b_run ) - { - this->b_run = b_run; - } + // creates a server socket. + int read_http(_socket *p_sock, char *c_zbuf, int &i_payloadoffset); + string read_http_line(_socket *p_sock); + + // small inline methods: + + string dump() { return ip_cache_map->dump(); } + bool get_server_() const { return b_run; } + bool get_run() const { return b_run; } + bool set_run( bool b_run ) { this->b_run = b_run; } + + sock(); + + int read_write(_socket* p_sock); + + int start(); void clean_ipcache(); - virtual int _make_server_socket(int i_port); + + // the chat stream there all the chat messages will sent through. + void chat_stream(_socket* p_sock, user* p_user, map<string,string> &map_params); //<< + virtual int _send(_socket *p_sock, const char *sz, int len); + virtual int _read(_socket *p_sock, char *sz, int len); + virtual int _close(_socket *p_sock); + virtual void _main_loop_init(); + #ifdef OPENSSL virtual bool _main_loop_do_ssl_stuff(int& i_new_sock); #endif - static void init_event_handlers(); - void init_server_event_handler(); + virtual _socket* _create_container(int& i_sock); + virtual int _make_server_socket(int i_port); }; #endif diff --git a/src/sock/sslsock.cpp b/src/sock/sslsock.cpp index 1541a23..494d572 100644 --- a/src/sock/sslsock.cpp +++ b/src/sock/sslsock.cpp @@ -1,12 +1,11 @@ /*:* *: File: ./src/sock/sslsock.cpp *: - *: yChat; Homepage: ychat.buetow.org; Version 0.9.0-CURRENT + *: yChat; Homepage: www.yChat.org; Version 0.8.3-CURRENT *: *: Copyright (C) 2003 Paul C. Buetow, Volker Richter *: Copyright (C) 2004 Paul C. Buetow *: Copyright (C) 2005 EXA Digital Solutions GbR - *: Copyright (C) 2006, 2007 Paul C. Buetow *: *: This program is free software; you can redistribute it and/or *: modify it under the terms of the GNU General Public License @@ -69,7 +68,7 @@ sslsock::_make_server_socket(int i_port) int i_sock = sock::_make_server_socket(i_port); - if (i_sock <= 0) + if(i_sock <= 0) { wrap::system_message(SSLERR1); return -1; @@ -116,17 +115,23 @@ sslsock::_make_server_socket(int i_port) return i_sock; } +void +sslsock::_main_loop_init() +{ + wrap::system_message(SOCKSEC); +} + bool sslsock::_main_loop_do_ssl_stuff(int& i_new_sock) { SSL* p_ssl = SSL_new(p_ctx); - if (p_ssl == NULL || i_new_sock < 0) + if( p_ssl == NULL || i_new_sock < 0) { wrap::system_message(SSLERR3); close(i_new_sock); - if (p_ssl != NULL) + if(p_ssl != NULL) SSL_free(p_ssl); return 1; @@ -135,7 +140,7 @@ sslsock::_main_loop_do_ssl_stuff(int& i_new_sock) else { SSL_set_fd(p_ssl, i_new_sock); - if (SSL_accept(p_ssl) == -1) + if(SSL_accept(p_ssl) == -1) { wrap::system_message(SSLERR4); close(i_new_sock); diff --git a/src/sock/sslsock.h b/src/sock/sslsock.h index 9f1fce8..8be232a 100644 --- a/src/sock/sslsock.h +++ b/src/sock/sslsock.h @@ -1,12 +1,11 @@ /*:* *: File: ./src/sock/sslsock.h *: - *: yChat; Homepage: ychat.buetow.org; Version 0.9.0-CURRENT + *: yChat; Homepage: www.yChat.org; Version 0.8.3-CURRENT *: *: Copyright (C) 2003 Paul C. Buetow, Volker Richter *: Copyright (C) 2004 Paul C. Buetow *: Copyright (C) 2005 EXA Digital Solutions GbR - *: Copyright (C) 2006, 2007 Paul C. Buetow *: *: This program is free software; you can redistribute it and/or *: modify it under the terms of the GNU General Public License @@ -56,6 +55,7 @@ public: int _send(_socket *p_sock, const char *sz, int len); int _read(_socket *p_sock, char *sz, int len); int _close(_socket *p_sock); + void _main_loop_init(); bool _main_loop_do_ssl_stuff(int &i_new_sock); _socket* _create_container(int& i_sock); int _make_server_socket(int i_port); |
