#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <pthread.h>
#include <wiringPi.h>
void* do_chat(void *);
char* word[10] = {"kill", "sibal", "gese", "18", "ssibal", "fuck", "fucking", "lol", "shut", "hell"}; // 필터링 할 욕설
int checkword(char *word,const char *find); // 문자열 욕설인지 비교
pthread_t thread;
pthread_mutex_t mutex;
#define MAX_NAME 100
int usercnt =0;
struct user{ // 소켓, 닉네임, 욕설 카운트
int clientsocket;
char name[MAX_NAME];
int checkcnt;
};
void* do_redLed();
void* do_yellowLed();
void* do_blueLed();
void* do_buzzer();
#define MAX_CLIENT 10
#define CHATDATA 1024
#define INVALID_SOCK -1
struct user list_c[MAX_CLIENT];
char escape[] = "exit";
char greeting[] = "Welcome to chatting room\n";
char CODE200[] = "Sorry No More Connection\n";
main(int argc, char *argv[])
{
wiringPiSetup();
pinMode(1, OUTPUT); // RED
pinMode(4, OUTPUT); // YELLOW
pinMode(5, OUTPUT); // GREEN
pinMode(6, OUTPUT); // PIAZO BUZZER
int c_socket, s_socket;
struct sockaddr_in s_addr, c_addr;
int len;
int nfds = 0;
int i, j, n;
fd_set read_fds;
int res;
if (argc < 2) {
printf("usage: %s port_number\n", argv[0]);
exit(-1);
}
if (pthread_mutex_init(&mutex, NULL) != 0) {
printf("Can not create mutex\n");
return -1;
}
s_socket = socket(PF_INET, SOCK_STREAM, 0);
memset(&s_addr, 0, sizeof(s_addr));
s_addr.sin_addr.s_addr = htonl(INADDR_ANY);
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(atoi(argv[1]));
if (bind(s_socket, (struct sockaddr *)&s_addr, sizeof(s_addr)) == -1) {
printf("Can not Bind\n");
return -1;
}
if(listen(s_socket, MAX_CLIENT) == -1) {
printf("listen Fail\n");
return -1;
}
//chatting server is ready blue light on
//digitalWrite(5, 1);
//delay(30000);
//digitalWrite(5, 0);
pthread_create(&thread, NULL, do_blueLed, NULL);
for (i = 0; i < MAX_CLIENT; i++)
list_c[i].clientsocket = INVALID_SOCK;
while(1) {
len = sizeof(c_addr);
c_socket = accept(s_socket, (struct sockaddr *)&c_addr, &len);
// user logged on !! yellow light on
//digitalWrite(4,1);
//delay(5000);
//digitalWrite(4,0);
pthread_create(&thread, NULL, do_yellowLed, NULL);
res = pushClient(c_socket);
if (res < 0) {
write(c_socket, CODE200, strlen(CODE200));
close(c_socket);
} else {
write(c_socket, greeting, strlen(greeting));
pthread_create(&thread, NULL, do_chat, (void *) c_socket);
}
}
}
void *
do_chat(void *arg)
{
int c_socket = (int) arg;
char chatData[CHATDATA];
int i, n, j, k, l, s, rcv, helpi, whoi, checki;
int checknum, start, checkI;
char *checkPoint;
int idCheck=0;
char temp[MAX_NAME]; // chatData COPY
char temp1[MAX_NAME]; // 받는 사람
char temp2[MAX_NAME]; // 보낼 메시지
char sendid[MAX_NAME]; // 보내는 사람 아이디
char sendtemp[13] = {"'s send -> "};
char send[MAX_NAME]; // 보내는 메시지 + 보내는 사람
char forhelp[MAX_NAME]; // help를 위한 복사본
char helpid[MAX_NAME]; // HELP 받을 ID
char help[400] = {"귓속말 : sendto 보낼닉네임 보낼내용\n금지어 : kill, sibal, gese, 18, ssibal, fuck, fucking, lol, shut, hell 입력 시 * 표시\n도움말 : /help\n접속명단 확인 : /Who\n채팅방 종료시 : exit\n"}; // help 설명문 작성
char forwho[MAX_NAME]; // who를 위한 복사본
char whoid[MAX_NAME]; // who 받을 id
char who[MAX_NAME]; // who 출력문 작성
char line[MAX_NAME] = {"\n"}; // 줄바꿈 위한
char whotext[MAX_NAME] = {"-- 접속 명단 --\n"}; // 접속명단 출력위한
char checkChat[MAX_NAME]; // checkChat 위해 저장
char forcheck[MAX_NAME]; // check를 위한 복사본
char checkid[MAX_NAME]; // checkChat 받을 id
char *token;
while(1) {
memset(chatData, 0, sizeof(chatData));
if ((n = read(c_socket, chatData, sizeof(chatData))) > 0 ) {
// filtering test! red light on, bujjer on
// strstr(chatData, badworkds)
// change badworkds -> ****
strcpy(temp,chatData); // ChatData를 temp에 카피 저장
strcpy(forhelp, chatData); //help를 위해 카피 저장
strcpy(forwho, chatData); // who를 위해 카피 저장
strcpy(forcheck, chatData); // chckChat 위해 카피 저장
token = strtok(forcheck, "[]"); // 욕설 하는사람 소켓번호 찾기
strcpy(checkid, token);
for(s=0; s<usercnt; s++){
if(strcmp(list_c[s].name, checkid)== 0){
checki = s;
}
}
for(checknum=0 ; checknum<10; checknum++){ // 욕설 문자열 비교
idCheck += checkword(chatData,word[checknum]);
}
if(idCheck !=0){ // 욕설 카운트
//digitalWrite(1, 1);
//delay(5000);
//digitalWrite(1, 0);
pthread_create(&thread, NULL, do_redLed, NULL);
pthread_create(&thread, NULL, do_buzzer, NULL);
list_c[checki].checkcnt += 1;
printf("%s - %d회 욕설\n",list_c[checki].name,list_c[checki].checkcnt);
}
idCheck =0;
// sendto 받는사람 보내는내용
if(strstr(temp, "sendto") != NULL){ // 문자열 중에 sendto 있으면 귓속말로 간다
//chatData [%s] : 내가 입력한 문자열로 들어옴
token= strtok(temp, " "); // [%s] 문자열 버림
strcpy(sendid, token);
token= strtok(NULL, " "); // : 문자열 버림
token=strtok(NULL, " "); // sendto 문자열 버림
token= strtok(NULL, " "); // 2번째 문자열(받는 사람)
strcpy(temp1, token); // 받는 사람=문자열 -> temp1 저장
token= strtok(NULL, " "); // 3번째 문자열(보낼 메시지)
strcpy(temp2,token); // 보낼 메시지=문자열 -> temp2 저장
for(j=0; j<usercnt; j++){ // 해당 유저이름 있으면 그 유저번호 찾음
if(strcmp(list_c[j].name, temp1) == 0 ){
rcv = j;
}
}
strcat(sendid, sendtemp);
strcat(sendid, temp2);
strcpy(send, sendid);
// 그 유저이름의 클라이언트 소켓에 보낼 메시지 보냄
write(list_c[rcv].clientsocket, send, sizeof(send));
}
else if(strstr(forhelp, "/help") != NULL){ // /help -> 해당 소켓 설명문 출력
token = strtok(forhelp, "[]");
strcpy(helpid, token);
for(k=0; k<usercnt; k++){
if(strcmp(list_c[k].name, helpid) == 0){
helpi = k;
}
}
write(list_c[helpi].clientsocket, help, sizeof(help));
}
else if(strstr(forwho, "/who") != NULL){ // /who -> 해당 소켓 리스트 출력
token = strtok(forwho, "[]");
strcpy(whoid, token);
for(l=0; l<usercnt; l++){
if(strcmp(list_c[l].name, whoid) == 0){
whoi = l;
}
}
strcat(who, whotext);
for(l=0; l<usercnt; l++){
strcat(who, list_c[l].name);
strcat(who, line);
}
write(list_c[whoi].clientsocket, who, sizeof(who));
}
// 귓속말 안하면 소켓번호 생성되있으면 소켓에 해당 채팅 보내라
// escape(exit)라면 pop해라 client를
else {
for (i = 0; i < MAX_CLIENT; i++) {
if (list_c[i].clientsocket != INVALID_SOCK) {
write(list_c[i].clientsocket, chatData, n);
}
if(strstr(chatData, escape) != NULL){
popClient(c_socket);
break;
}
}
}
}
}
}
int
pushClient(int c_socket) {
int i, n;
char chatData[CHATDATA];
char tmp[MAX_NAME]; // 닉네임 저장 위한
char tokensep1[] = "[]";
char *token;
// 유저 닉네임들 배열에 넣기
if(( n = read(c_socket, chatData, sizeof(chatData))) > 0 ){
token = strtok(chatData, tokensep1);
strcpy(list_c[usercnt].name, token);
list_c[usercnt].checkcnt=0;
usercnt++;
}
// -1로 초기화했고 들어오면 c_socket번호 넣어준다 (위에서 소켓번호 정상출력 4부터)
for (i = 0; i < MAX_CLIENT; i++) {
read(c_socket, chatData, sizeof(chatData));
token = strtok(chatData, tokensep1);
pthread_mutex_lock(&mutex);
if(list_c[i].clientsocket == INVALID_SOCK) {
list_c[i].clientsocket = c_socket;
strcpy(list_c[i].name, token);
pthread_mutex_unlock(&mutex);
return i;
}
pthread_mutex_unlock(&mutex);
}
return -1;
}
int
popClient(int s)
{
int i;
close(s);
for (i = 0; i < MAX_CLIENT; i++) {
pthread_mutex_lock(&mutex);
if ( s == list_c[i].clientsocket ) {
list_c[i].clientsocket = INVALID_SOCK;
pthread_mutex_unlock(&mutex);
break;
}
pthread_mutex_unlock(&mutex);
}
return 0;
}
int checkword(char *word, const char *find){ // 욕설 찾아서 그 부분만큼 *
int cnt, find_size;
char *pos;
int cnt2= 0;
find_size = strlen(find);
while((pos = strstr(word,find))!=NULL)
{
for(cnt = 0; cnt<find_size; cnt++){
*(word + (strlen(word)-strlen(pos))+cnt) = '*';
}
cnt2 += 1;
}
return cnt2;
}
void* do_redLed(){
digitalWrite(1, 1);
delay(4000);
digitalWrite(1, 0);
}
void* do_yellowLed(){
digitalWrite(4, 1);
delay(10000);
digitalWrite(4, 0);
}
void* do_blueLed(){
digitalWrite(5, 1);
delay(100000);
digitalWrite(5, 0);
}
void* do_buzzer(){
digitalWrite(6, 1);
delay(4000);
digitalWrite(6, 0);
}