/* * Parse incoming data * Types of messages and their responses are: * NEW: <from> * Response --> NEW: <status> * CHNAME: <old> : <new> * Response --> CHNAME: <status> * QUERY: <from> * Response --> ONLINE: <user1> : <user2> : <user3> : .... * SEND: <from> : <to> : <message> * Response --> SENT: <to> : <statusMessage> * BCAST: <from> : <message> * Response --> SENT: <from> : <status> * * /toclient/ RECV: <from> : <message> */ void processRequest(int fromSocket, char* stream){ std::vector<std::string> tokens; char* dump = strdup(stream); /* Create a duplicate stream */ splitCharStream(dump, DELIM, 1, &tokens); /* Retrieve the kind of message */ delete dump; std::string reqType = tokens[0]; int TYPE_FLAG = -1, delimCount=-1; if(reqType=="CHNAME"){ TYPE_FLAG = TYPE_CHNAME; delimCount = 1; } else if(reqType=="NEW"){ TYPE_FLAG = TYPE_NEW; delimCount = 0; } else if(reqType=="QUERY"){ TYPE_FLAG = TYPE_QUERY; delimCount = 0; } else if(reqType=="SEND"){ TYPE_FLAG = TYPE_SEND; delimCount = 2; } else if(reqType=="BCAST"){ TYPE_FLAG = TYPE_BCAST; delimCount = 1; } if(TYPE_FLAG==-1) return; #ifdef __DEBUG__ std::cout<<TYPE_FLAG<<" --- "; #endif splitCharStream(strdup(tokens[1].c_str()), DELIM, delimCount, &tokens); /* Based on kind retrieve other param list */ std::string fromUser = tokens[0]; std::string toUser, message; if(TYPE_FLAG == TYPE_CHNAME){ toUser = tokens[1]; #ifdef __INFO__ std::cout<<"\""<<fromUser<<"\" changing name to \""<<toUser<<"\"."<<std::endl; #endif int curSock = getFromConnectionTable(fromUser); std::string reply = "CHNAME:"+toUser+":"; if(curSock==-1){ reply += "fail"; } else{ curSock = getFromConnectionTable(toUser); if(curSock==-1){ removeFromConnectionTable(fromSocket); addToConnectionTable(toUser, fromSocket); reply += "success"; } else{ reply += "duplicate"; } } int s = send(fromSocket, reply.c_str(), reply.length(), 0); if(s<0){ ERROR = E_SEND; error_message = "Unable to send query reply."; #ifdef __DEBUG__ std::cout<<error_message<<std::endl; #endif } } else if(TYPE_FLAG == TYPE_NEW){ #ifdef __INFO__ std::cout<<"\""<<fromUser<<"\" new registration."<<std::endl; #endif int oldSock = getFromConnectionTable(fromUser); std::string reply = "duplicate"; if(oldSock==-1){ addToConnectionTable(fromUser, fromSocket); /* Add user socket pair to table */ reply = "registered"; } #ifdef __INFO__ std::cout<<"\""<<fromUser<<"\" reg. status: "<<reply<<"."<<std::endl; #endif int s = send(fromSocket, reply.c_str(), reply.length(), 0); if(s<0){ ERROR = E_SEND; error_message = "Unable to send query reply."; #ifdef __DEBUG__ std::cout<<error_message<<std::endl; #endif } } else if(TYPE_FLAG == TYPE_QUERY){ #ifdef __INFO__ std::cout<<"\""<<fromUser<<"\" queried."<<std::endl; #endif std::string onlineList = getOnlineList(fromUser); int s = send(fromSocket, onlineList.c_str(), onlineList.length(), 0); if(s<0){ ERROR = E_SEND; error_message = "Unable to send query reply."; #ifdef __DEBUG__ std::cout<<error_message<<std::endl; #endif } } else if(TYPE_FLAG == TYPE_SEND){ toUser = tokens[1]; message = tokens[2]; #ifdef __INFO__ std::cout<<"\""<<fromUser<<"\" sending message to \""<<toUser<<"\"."<<std::endl; #endif /* Send message to desired target username */ int status = sendMessage(toUser, fromUser, message); std::string reply = "SENT: "+toUser+" : "; if(status==-1){ reply += error_message; #ifdef __DEBUG__ std::cout<<"\""<<fromUser<<"\" could not send a message to \""<<toUser<<"\". "<<std::endl; #endif } else{ reply += "success"; #ifdef __DEBUG__ std::cout<<"\""<<fromUser<<"\" sent a message to \""<<toUser<<"\"."<<std::endl; #endif } /* Report back to the sender */ int s = send(fromSocket, reply.c_str(), reply.length(), 0); if(s<0){ ERROR = E_SEND; error_message = "Unable to send message status."; #ifdef __DEBUG__ std::cout<<error_message<<std::endl; #endif } } else if(TYPE_FLAG == TYPE_BCAST){ message = tokens[1]; std::string bcast = "RECV:"+fromUser+":"+message; #ifdef __INFO__ std::cout<<"Broadcast from \""+fromUser+"\" : "<<message<<std::endl; #endif int status; Connections::iterator it = conn.begin(); while(it!=conn.end()){ if(it->first != fromUser){ status = send(it->second, bcast.c_str(), bcast.length(), 0 ); } ++it; } std::string reply = "SENT:"+fromUser+":b_success"; /* Report back to the broadcaster */ int s = send(fromSocket, reply.c_str(), reply.length(), 0); if(s<0){ ERROR = E_SEND; error_message = "Unable to send message status."; #ifdef __DEBUG__ std::cout<<error_message<<std::endl; #endif } } }
void *accepted(void *csd){ PEER *p = (PEER *) csd; DATA *data = malloc(sizeof(DATA)); DATA *reply = malloc(sizeof(DATA)); int client_sd = p->client_sd; int len, status; int id = p->id; while(1){ printf("B4 recv data\n"); data = recv_data(client_sd,(unsigned int *)&len,&status); printf("AFTER recv data\n"); switch(status){ case -1: case -2: printf("Status = error(%d)\n", status); close(client_sd); offline(id); printf("[Disconnected] Client %s:%d\n", getClientAddr(&p->client_addr), ntohs(p->client_addr.sin_port)); return 0; default: break; } printf("DATA command: %d\n", data->command); switch(data->command){ case LOGIN: printf("Client %s:%d: [LOGIN] Username="******"\n"); data->arg->ip = ntohl(p->client_addr.sin_addr.s_addr); status = online(data->arg, id); if(status >= 0 && status < 10){ reply = newHeader(); reply->command = LOGIN_OK; reply->length = 1; if(!send_data(client_sd,reply,(unsigned int*)&len)) return 0; }else{ printf("[ERROR] Client %s:%d ", getClientAddr(&p->client_addr), ntohs(p->client_addr.sin_port)); reply = newHeader(); reply->command = ERROR; switch(status){ case -1: printf("maximum connection exceed!"); reply->error = TOO_MUCH_CONN; break; case -2: printf("duplication of name!"); reply->error = SAME_NAME; break; case -3: printf("duplication of port and IP address!"); reply->error = SAME_CONN; } printf("\n"); reply->length = 7; if(!send_data(client_sd,reply,(unsigned int*)&len)) return 0; close(client_sd); printf("[Disconnected] Client %s:%d\n", getClientAddr(&p->client_addr), ntohs(p->client_addr.sin_port)); return 0; } break; case GET_LIST: printf("Client %s:%d: GET_LIST\n", getClientAddr(&p->client_addr), ntohs(p->client_addr.sin_port)); reply = newHeader(); reply->command = GET_LIST_OK; getOnlineList(reply); reply->length += 7; if(!send_data(client_sd,reply,(unsigned int*)&len)) return 0; break; default: printf("Client %s:%d: Unknown command\n", getClientAddr(&p->client_addr), ntohs(p->client_addr.sin_port)); break; } } if(client_sd) close(client_sd); offline(id); printOnlineList(); printf("[Disconnected] Client %s:%d\n", getClientAddr(&p->client_addr), p->client_addr.sin_port); }