diff options
Diffstat (limited to 'src/server/chat.cpp')
-rw-r--r-- | src/server/chat.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/server/chat.cpp b/src/server/chat.cpp new file mode 100644 index 0000000..a9ecda1 --- /dev/null +++ b/src/server/chat.cpp @@ -0,0 +1,196 @@ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + +#include "chat.hpp" +#include "rooms.hpp" + +static const int qlen_for_listen = 6; + +void ChatSession::Send(const char *msg) +{ + CONSOLE_LOG("%s", msg); + write(GetFd(), msg, strlen(msg)); +} + +void ChatSession::Handle(bool r, bool w) +{ + if(!r) + return; + + // this functions create for support any client, not one WantChat client: + if(buf_used >= (int)sizeof(buffer)) { + buf_used = 0; + ignoring = true; + } + if(ignoring) { + CONSOLE_LOG("Ignore the message, it's so big\n"); + ReadAndIgnore(); + } + else + ReadAndCheck(); +} + +void ChatSession::ReadAndIgnore() +{ + int rc = read(GetFd(), buffer, sizeof(buffer)); + CONSOLE_LOG("readI return %d bytes\n", rc); + if(rc < 1) { + the_master->CloseSession(this); + return; + } + + for(int i = 0; i < rc; i++) + if(buffer[i] == '\n') + { // stop ignoring! + CONSOLE_LOG("ReadAndIgnore: find \\n\n"); + int rest = rc - i - 1; + if(rest > 0) + memmove(buffer, buffer + i + 1, rest); + buf_used = rest; + ignoring = 0; + CheckLines(); + } +} + +void ChatSession::ReadAndCheck() +{ + int rc = read(GetFd(), buffer+buf_used, sizeof(buffer)-buf_used); + CONSOLE_LOG("readC return %d bytes\n", rc); + if(rc < 1) { + the_master->LeaveMessage(this); + the_master->CloseSession(this); + return; + } + buf_used += rc; + CheckLines(); +} + +void ChatSession::CheckLines() +{ + if(buf_used <= 0) + return; + + for(int i = 0; i < buf_used; i++) { + if(buffer[i] == '\n') { + CONSOLE_LOG("[CheckLines] buffer[i] == \\n i = %d\n", i); + buffer[i] = 0; + if(i > 0 && buffer[i-1] == '\r') + buffer[i-1] = 0; + + CONSOLE_LOG("printed: %s\n", buffer); + the_master->HandleMessage(this, buffer); + + int rest = buf_used - i - 1; + memmove(buffer, buffer + i + 1, rest); + buf_used = rest; + CONSOLE_LOG("[CheckLines] new buf_used = %d\n", buf_used); + CheckLines(); + return; + } + } +} + +void ChatSession::ChangeName(const char *n_name) +{ + for(int i = 0; i < max_name_len; i++) + name[i] = 0; + + strcpy(name, n_name); + char *msg = new char[max_msg_len]; + sprintf(msg, "Now your name is %s\n", name); + + this->Send(msg); + + delete[] msg; +} + +////////////////////////////////////////////////////////////// + +Server::Server(EventSelector *sel, int fd) + : FdHandler(fd), the_selector(sel) +{ + the_selector->Add(this); + lobby = new ChatRoom(this, true); +} + +Server::~Server() +{ + if(room) + delete[] room; + + the_selector->Remove(this); +} + +Server *Server::Start(EventSelector *sel, int port) +{ + int in_d = socket(AF_INET, SOCK_STREAM, 0); + if(in_d == -1) + return 0; + + int opt = 1; + setsockopt(in_d, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + int res = bind(in_d, (struct sockaddr*) &addr, sizeof(addr)); + if(res == -1) + return 0; + + res = listen(in_d, qlen_for_listen); + if(res == -1) + return 0; + + return new Server(sel, in_d); +} + +void Server::Handle(bool r, bool w) +{ + if(!r) + return; + + struct sockaddr_in addr; + socklen_t len = sizeof(addr); + int sd = accept(GetFd(), (struct sockaddr*) &addr, &len); + if(sd == -1) + return; + + ChatSession *s = new ChatSession(lobby, sd); + lobby->AddSession(s); + the_selector->Add(s); +} + +int Server::AddRoom() +{ + if(!room) { + room_len = 16; + room = new ChatRoom*[room_len]; + for(int i = 0; i < room_len; i++) + room[i] = 0; + } + + int id = -1; + for(int i = 0; i < room_len; i++) { + if(room[i] == 0) { + id = 0; + room[i] = new ChatRoom(this, false); + } + } + + if(id == -1) { + ChatRoom **tmp = new ChatRoom*[room_len+1]; + for(int i = 0; i < room_len; i++) { + tmp[i] = room[i]; + } + tmp[room_len] = new ChatRoom(this, false); + room_len += 1; + } + + return id; +}
\ No newline at end of file |