
About: This was a project made for COP 3404 Systems Programming. It's a chat lobby made for the UNF LPAR of the IBM mainframe UNIX system services (USS) and a "true" linux partition of the same mainframe. Users on the server could simply type 'chat' and enter the lobby. Then, within the lobby users could see and chat with other online users. Optionally users could send private chat requests to one another and break off into 1 on 1 chats.
The program was written in C using a client-server model with network sockets. The clients make use of the curses lobby for a fancy display. The server makes heavy use of poll() to manage the multiple connections, clients use threads to listen and talk at the same time.


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define KNRM "\x27[0m"
#define KRED "\x27[31m"
#define KGRN "\x27[32m"
#define KYEL "\x27[33m"
#define KBLU "\x27[34m"
#define KMAG "\x27[35m"
#define KCYN "\x27[36m"
#define KWHT "\x27[37m"
#define SERVER_HOSTNAME "zos.ospreys.biz"
#define SERVER_PORT "50074"
#define CHAT_CAPACITY 100
#define MSG_LEN 256
// User status codes
typedef enum {
ONLINE = 0,
ACTIVE = 1,
PENDING = 2,
PRIVATE = 3,
OFFLINE = 4
} UserStatus;
//a struct to hold users
struct user{
char username[24]; //their username
int fd; //the server-given fd
int partner; //the fd of the partner
int status; //0 online, 1 active, 2 pending, 3 private, 4 offline
struct user* next;
};
struct message {
char messages[CHAT_CAPACITY][MSG_LEN];
int start; // oldest message index
int count; // how many messages are currently stored
};
//GLOBAL VARIABLES
struct user* userlist = NULL;
struct message chatlog;
int myFd; //the fd the server has assigned you
void init_chatlog(struct message *log) {
log->start = 0;
log->count = 0;
}
void add_message(struct message *log, const char *msg) {
int index;
if (log->count < CHAT_CAPACITY) {
// There is space, append at (start + count) % CHAT_CAPACITY
index = (log->start + log->count) % CHAT_CAPACITY;
log->count++;
} else {
// Full overwrite oldest
index = log->start;
log->start = (log->start + 1) % CHAT_CAPACITY;
}
strncpy(log->messages[index], msg, MSG_LEN - 1);
log->messages[index][MSG_LEN - 1] = '\0';
}
void print_chatlog(struct message* log) {
for (int i = 0; i < log->count; i++) {
int index = (log->start + i) % CHAT_CAPACITY;
printf("%s", log->messages[index]);
}
}
struct user* createUser(char* username, int fd, int partner, int status) {
struct user* newNode = (struct user*)malloc(sizeof(struct user));
strcpy(newNode->username, username);
newNode->fd = fd;
newNode->partner = partner;
newNode->status = status;
newNode->next = NULL;
return newNode;
}
/*
*insertUser(username,fd,partner,status)
*/
struct user* insertUser(struct user** head, char* username, int fd, int partner, int status) { //*head is a pointer to the pointer of the head
struct user* newSymbol = createUser(username, fd, partner, status);
if (*head == NULL) {
*head = newSymbol;
return newSymbol;
}
struct user* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newSymbol;
return newSymbol;
}
void print_userlist(){
struct user* temp = userlist;
printf("active users\n");
printf("-----------------------------\n");
while(temp != NULL) {
if(temp->status == 1 || temp->status == 2){
if(temp->fd == myFd){
printf("%s%s%s\n",KYEL,temp->username,KNRM);
}
else{
printf("%s%s%s\n",KBLU,temp->username,KNRM);
}
}
temp = temp->next;
}
temp = userlist;
printf("private chat\n");
printf("-----------------------------\n");
while(temp != NULL) {
if(temp->status == 3){
if(temp->fd == myFd){
printf("%s%s%s\n",KYEL,temp->username,KNRM);
}
else{
printf("%s%s%s\n",KGRN,temp->username,KNRM);
}
}
temp = temp->next;
}
temp = userlist;
printf("online\n");
printf("-----------------------------\n");
while(temp != NULL) {
if(temp->status == 0){
if(temp->fd == myFd){
printf("%s%s%s\n",KYEL,temp->username,KNRM);
}
else{
printf("%s%s%s\n",KCYN,temp->username,KNRM);
}
}
temp = temp->next;
}
}
int updateUser(struct user* head,int fd,const char* username,int partner,int status){
struct user* curr = head;
while (curr != NULL) {
if (curr->fd == fd) {
// Update all fields
strncpy(curr->username, username, sizeof(curr->username) - 1);
curr->username[sizeof(curr->username) - 1] = '\0';
curr->partner = partner;
curr->status = status;
return 1; // success
}
curr = curr->next;
}
return 0; // not found
}
void removeUser(struct user* head, int fd) { //*head is a pointer to the pointer of the head
struct user* temp;
struct user* last;
temp = head;
if(temp == NULL){
return;
}
while(temp->fd != fd){
if(temp->next == NULL){
return;
}
last = temp;
temp = temp->next;
}
last->next = temp->next;
free(temp);
print_userlist();
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa){
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
//connects to server then returns the server fd
int connect_to_server(const char *host, const char *port){
struct addrinfo hints, *servinfo, *p;
int rv;
int sockfd = -1;
char ipstr[INET6_ADDRSTRLEN];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; // IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP
if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return -1;
}
// loop through all results and connect to the first we can
for (p = servinfo; p != NULL; p = p->ai_next) {
// Make a socket
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd == -1) {
perror("socket");
continue;
}
// Print what we're trying to connect to
inet_ntop(p->ai_family,
get_in_addr((struct sockaddr *)p->ai_addr),
ipstr, sizeof ipstr);
printf("client: attempting connection to %s...\n", ipstr);
// Try to connect
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
perror("connect");
close(sockfd);
sockfd = -1;
continue;
}
// Success!
break;
}
freeaddrinfo(servinfo);
if (sockfd == -1) {
fprintf(stderr, "client: failed to connect to server\n");
}
return sockfd;
}
char* get_username(struct user* head,int fd){
struct user* temp = head;
while(fd != temp->fd){
if(temp->next == NULL){
return NULL;
}
temp=temp->next;
}
return temp->username;
}
void parse_user(const char buffer[32]) {
char username[12];
int fd, partner, status;
int matched = sscanf(buffer, "%11[^,],%d,%d,%d",
username, &fd, &partner, &status);
if (matched == 4) {
insertUser(&userlist, username, fd, partner, status);
}
}
void change_user(char buffer[48]) {
char username[12];
int fd, partner, status;
// Parse the server message safely
int matched = sscanf(buffer, "{%11[^,],%d,%d,%d}", username, &fd, &partner, &status);
username[11] = '\0'; // ensure null termination
printf("[CHANGE_USER] matched=%d user=%s fd=%d partner=%d status=%d\n",
matched, username, fd, partner, status);
if (matched != 4) return;
// If the update involves this client
if (fd == myFd) {
switch (status) {
case PRIVATE:
printf("BEGIN PRIVATE CHAT\n");
return;
case PENDING:
printf("CHAT REQUEST FROM %s\n", get_username(userlist,partner));
return;
case ACTIVE:
printf("END PRIVATE CHAT\n");
return;
default:
// ignore other statuses for self
return;
}
}
struct user* temp = userlist;
while(temp->fd != myFd){
if(temp->next == NULL){
insertUser(&userlist,username,fd,partner,status);
return;
}
temp=temp->next;
}
if(fd == temp->partner){
printf("PARTNER DISCONNECTED!\n");
temp->partner = 0;
temp->status = 1;
}
// Update or remove other users
if (status > PRIVATE) {
removeUser(userlist, fd);
} else {
updateUser(userlist, fd, username, partner, status);
}
}
void get_userlist(int server_fd){
int flag = 1;
while(flag == 1){
char buf[32];
char c;
recv(server_fd, &c, 1, 0);
while(c == '{'){
int i = 0;
recv(server_fd, &c, 1, 0);
while(c != '}'){
buf[i] = c;
i++;
recv(server_fd, &c, 1, 0);
}
if(strcmp(buf,"END") == 0){
flag = 0;
break;
}
else{
parse_user(buf);
memset(buf,0,strlen(buf));
recv(server_fd, &c, 1, 0);
}
}
}
//we are the last user
struct user* temp = userlist;
while(temp->next != NULL) {
temp = temp->next;
}
myFd = temp->fd;
printf("my fd:%d\n",myFd);
}
void recv_loop(int sockfd) {
char c;
char buffer[32];
int buf_idx = 0;
int in_packet = 0;
ssize_t n;
while (1) {
n = recv(sockfd, &c, 1, 0);
if (n <= 0) {
if (n == 0) {
printf("Connection closed\n");
} else {
perror("recv error");
}
break;
}
if (c == '{') {
in_packet = 1;
buf_idx = 0;
buffer[buf_idx++] = c;
} else if (in_packet) {
if (buf_idx < 31) {
buffer[buf_idx++] = c;
}
if (c == '}') {
buffer[buf_idx] = '\0';
change_user(buffer);
in_packet = 0;
buf_idx = 0;
}
} else {
putchar(c);
fflush(stdout);
}
}
}
#include
#include
#include
/*
* cut_substring:
* src = original null-terminated string
* start = index where substring begins
* len = length of substring to cut
*
* Returns:
* *out_cut = newly allocated substring
* *out_remaining = newly allocated string with the substring removed
*
* Caller must free both outputs.
*/
void cut_substring(const char *src, size_t start, size_t len,
char **out_cut, char **out_remaining){
size_t src_len = strlen(src);
// Bounds guard
if (start > src_len) start = src_len;
if (start + len > src_len) len = src_len - start;
// Allocate substring
*out_cut = malloc(len + 1);
if (!*out_cut) {
perror("malloc");
exit(1);
}
memcpy(*out_cut, src + start, len);
(*out_cut)[len] = '\0';
// Allocate remaining string
size_t remaining_len = src_len - len;
*out_remaining = malloc(remaining_len + 1);
if (!*out_remaining) {
perror("malloc");
exit(1);
}
// Copy the two parts around the cut-out region
memcpy(*out_remaining, src, start); // left part
memcpy(*out_remaining + start, src + start + len, // right part
src_len - (start + len));
(*out_remaining)[remaining_len] = '\0';
}
int main(int argc,char* argv[]){
init_chatlog(&chatlog);
//join server
int server_fd = connect_to_server(SERVER_HOSTNAME,SERVER_PORT);
if(server_fd < 0){
return -1;
}
printf("connected!\n");
char username[24];
strcpy(username,getlogin());
printf("username: %s\n",username);
send(server_fd, username, sizeof(username), 0);
get_userlist(server_fd);
print_userlist();
printf("ready to chat!\n");
struct pollfd fds[2];
fds[0].fd = STDIN_FILENO;
fds[0].events = POLLIN;
fds[1].fd = server_fd;
fds[1].events = POLLIN;
char buf[256];
char c;
for (;;) {
int rv = poll(fds, 2, -1);
if (rv < 0) {
perror("poll");
exit(1);
}
// ---- stdin -> server ----
if (fds[0].revents & POLLIN) {
ssize_t len = read(STDIN_FILENO, buf, sizeof(buf));
if (len <= 0) {
printf("stdin closed\n");
break;
}
// Send EXACTLY len bytes
ssize_t sent = send(server_fd, buf, len, 0);
if (sent <= 0) {
perror("send");
break;
}
}
// ---- server -> client ----
if (fds[1].revents & POLLIN) {
ssize_t len = recv(server_fd, buf, sizeof(buf) - 1, 0);
if (len == 0) {
printf("server disconnected\n");
break;
}
if (len < 0) {
perror("recv");
break;
}
buf[len] = '\0';
for(int i=0;i
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_HOSTNAME "zos.ospreys.biz"
#define SERVER_PORT "50074"
#define BACKLOG 20
#define CHAT_CAPACITY 100
#define MSG_LEN 256
//GLOBABL VARIABLES
struct user* userlist = NULL;
struct message chatlog;
//a struct to hold users
struct user{
char username[24]; //their username
int fd; //the server-given fd
int partner; //the fd of the partner
int status; //0 online, 1 active, 2 pending, 3 private, 4 offline
struct user* next;
};
//this is a ring buffer
//a type of fixed size array that wraps back around on itself
struct message {
char messages[CHAT_CAPACITY][MSG_LEN];
int start; // oldest message index
int count; // how many messages are currently stored
};
void init_chatlog(struct message *log) {
log->start = 0;
log->count = 0;
}
void add_message(struct message *log, const char *msg) {
int index;
if (log->count < CHAT_CAPACITY) {
// There is space, append at (start + count) % CHAT_CAPACITY
index = (log->start + log->count) % CHAT_CAPACITY;
log->count++;
} else {
// Full overwrite oldest
index = log->start;
log->start = (log->start + 1) % CHAT_CAPACITY;
}
strncpy(log->messages[index], msg, MSG_LEN - 1);
log->messages[index][MSG_LEN - 1] = '\0';
}
void print_chatlog(struct message* log) {
for (int i = 0; i < log->count; i++) {
int index = (log->start + i) % CHAT_CAPACITY;
printf("%s", log->messages[index]);
}
}
// Remove an index from the set
void del_from_pfds(struct pollfd pfds[], int i, int *fd_count){
// Copy the one from the end over this one
pfds[i] = pfds[*fd_count-1];
(*fd_count)--;
}
// Return a listening socket
int get_listener_socket(void){
int listener; // Listening socket descriptor
int yes=1; // For setsockopt() SO_REUSEADDR, below
int rv;
struct addrinfo hints, *ai, *p;
// Get us a socket and bind it
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if ((rv = getaddrinfo(NULL, SERVER_PORT, &hints, &ai)) != 0) {
fprintf(stderr, "selectserver: %s\n", gai_strerror(rv));
exit(1);
}
for(p = ai; p != NULL; p = p->ai_next) {
listener = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (listener < 0) {
continue;
}
// Lose the pesky "address already in use" error message
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
if (bind(listener, p->ai_addr, p->ai_addrlen) < 0) {
close(listener);
continue;
}
break;
}
// If we got here, it means we didn't get bound
if (p == NULL) {
return -1;
}
freeaddrinfo(ai); // All done with this
// Listen
if (listen(listener, 10) == -1) {
return -1;
}
return listener;
}
int recv_all(int fd, void *buf, int len) {
int total = 0;
int n;
while (total < len) {
n = recv(fd, (char*)buf + total, len - total, 0);
if (n <= 0) {
return n;
}
total += n;
}
return 1;
}
void removeUser(struct user* head, int fd) { //*head is a pointer to the pointer of the head
struct user* temp;
struct user* last;
temp = head;
if(temp == NULL){
return;
}
while(temp->fd != fd){
if(temp->next == NULL){
return;
}
last = temp;
temp = temp->next;
}
last->next = temp->next;
free(temp);
}
char* get_username(struct user* head,int fd){
struct user* temp = head;
while(fd != temp->fd){
if(temp->next == NULL){
return NULL;
}
temp=temp->next;
}
return temp->username;
}
struct user* createUser(char* username, int fd, int partner, int status) {
struct user* newNode = (struct user*)malloc(sizeof(struct user));
strcpy(newNode->username, username);
newNode->fd = fd;
newNode->partner = partner;
newNode->status = status;
newNode->next = NULL;
return newNode;
}
struct user* get_user(struct user* userlist,int fd){
struct user* temp = userlist;
while(temp->fd != fd){
if(temp->next == NULL){
return NULL;
}
temp=temp->next;
}
return temp;
}
struct user* insertUser(struct user** head, char* username, int fd, int partner, int status) { //*head is a pointer to the pointer of the head
struct user* newSymbol = createUser(username, fd, partner, status);
if (*head == NULL) {
*head = newSymbol;
return newSymbol;
}
struct user* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newSymbol;
return newSymbol;
}
// Add a new file descriptor to the set
void add_to_pfds(struct pollfd *pfds[], int newfd, int *fd_count, int *fd_size){
// If we don't have room, add more space in the pfds array
if (*fd_count == *fd_size) {
*fd_size *= 2; // Double it
*pfds = realloc(*pfds, sizeof(**pfds) * (*fd_size));
}
(*pfds)[*fd_count].fd = newfd;
(*pfds)[*fd_count].events = POLLIN; // Check ready-to-read
(*fd_count)++;
}
int add_new_client(int listener,struct pollfd **pfds,int *fd_count,int *fd_size){
struct sockaddr_storage remoteaddr;
socklen_t addrlen = sizeof remoteaddr;
char remoteIP[INET6_ADDRSTRLEN];
int newfd = accept(listener, (struct sockaddr *)&remoteaddr, &addrlen);
if (newfd == -1) {
perror("accept");
return -1;
}
char username[24];
int nbytes = recv(newfd, username, sizeof(username), 0);
username[nbytes] = '\0';
printf("%s connected!\n",username);
insertUser(&userlist,username,newfd,0,1);
struct user* temp = userlist;
while(temp != NULL) {
char msg[48];
snprintf(msg,sizeof(msg),"{%s,%d,%d,%d}",temp->username,temp->fd,temp->partner,temp->status);
send(newfd,msg,strlen(msg),0);
temp = temp->next;
}
send(newfd,"{END}",5,0);
for (int i = 0; i < chatlog.count; i++) {
int index = (chatlog.start + i) % CHAT_CAPACITY;
char msg[512];
snprintf(msg, sizeof(msg), "%s", chatlog.messages[index]);
send(newfd, msg, strlen(msg), 0);
}
add_to_pfds(pfds, newfd, fd_count, fd_size);
return newfd;
}
void command_handler(char buf[255], struct pollfd **pfds, int sender_fd) {
int i = 0;
// find the '/' command
while (buf[i] != '/' && buf[i] != '\0') i++;
if (buf[i] == '\0') return; // no command
char *start = buf + i + 1;
char *command = strtok(start, " \n");
if (!command) return;
struct user *temp = userlist;
while (temp && temp->fd != sender_fd)
temp = temp->next;
if (!temp) return; // sender not found
char notify[128];
if (strcmp(command, "chat") == 0) {
char *operand = strtok(NULL, " \n");
if (!operand) return;
int their_fd = atoi(operand);
struct user *target = userlist;
while (target && target->fd != their_fd)
target = target->next;
if (!target) return; // recipient not found
if (temp->status == 1 && target->status == 1) {
target->status = 2;
target->partner = sender_fd;
snprintf(notify, sizeof(notify), "{%s,%d,%d,%d}",
target->username,target->fd,target->partner,target->status);
send(sender_fd, notify, strlen(notify), 0);
send(their_fd, notify, strlen(notify), 0);
} else {
snprintf(notify, sizeof(notify),
"You can't private chat with them right now\n");
send(sender_fd, notify, strlen(notify), 0);
}
}
else if (strcmp(command, "accept") == 0) {
if (temp->status != 2) {
snprintf(notify, sizeof(notify),
"You don't have any chat invites\n");
send(sender_fd, notify, strlen(notify), 0);
return;
}
struct user *partner = userlist;
while (partner && partner->fd != temp->partner)
partner = partner->next;
if (!partner) return;
temp->status = 3;
partner->status = 3;
partner->partner = sender_fd;
// notify both users
snprintf(notify, sizeof(notify), "{%s,%d,%d,%d}",
temp->username, temp->fd, temp->partner, temp->status);
send(sender_fd, notify, strlen(notify), 0);
send(partner->fd, notify, strlen(notify), 0);
snprintf(notify, sizeof(notify), "{%s,%d,%d,%d}",
partner->username, partner->fd, partner->partner, partner->status);
send(sender_fd, notify, strlen(notify), 0);
send(partner->fd, notify, strlen(notify), 0);
}
else if (strcmp(command, "deny") == 0) {
if (temp->status != 2) return;
struct user *partner = userlist;
while (partner && partner->fd != temp->partner)
partner = partner->next;
if (!partner) return;
temp->status = 1; // back to active
temp->partner = 0;
partner->status = 1;
partner->partner = 0;
snprintf(notify, sizeof(notify), "{%s,%d,%d,%d}",
temp->username, temp->fd, temp->partner, temp->status);
send(sender_fd, notify, strlen(notify), 0);
send(partner->fd, notify, strlen(notify), 0);
}
else if (strcmp(command, "exit") == 0) {
if (temp->status != 3) return;
struct user *partner = userlist;
while (partner && partner->fd != temp->partner)
partner = partner->next;
if (!partner) return;
temp->status = 1;
temp->partner = 0;
partner->status = 1;
partner->partner = 0;
snprintf(notify, sizeof(notify), "{%s,%d,%d,%d}",
temp->username, temp->fd, temp->partner, temp->status);
send(sender_fd, notify, strlen(notify), 0);
send(partner->fd, notify, strlen(notify), 0);
snprintf(notify, sizeof(notify), "{%s,%d,%d,%d}",
partner->username, partner->fd, partner->partner, partner->status);
send(sender_fd, notify, strlen(notify), 0);
send(partner->fd, notify, strlen(notify), 0);
}
}
int main(int argc, char* argv[]){
int listener;
struct sockaddr_in my_addr;
init_chatlog(&chatlog);
//create a socket
listener = get_listener_socket();
if (listener < 0){
perror("Socket Error");
exit(1);
}
printf("listening on %s:%s\n",SERVER_HOSTNAME,SERVER_PORT);
//make a struct to hold all the connections
int fd_count = 0;
int fd_size = 5;
struct pollfd *pfds = malloc(sizeof *pfds * fd_size);
//make lister connection #1
pfds[0].fd = listener;
pfds[0].events = POLLIN;
fd_count = 1;
char buf[255];
for (;;) {
int poll_count = poll(pfds, fd_count, -1);
if (poll_count == -1) {
perror("poll");
exit(1);
}
for (int i = 0; i < fd_count; i++) {
// Only act when there is data or a new connection
if (pfds[i].revents & POLLIN) {
// New client connecting?
if (pfds[i].fd == listener) {
int newfd = add_new_client(listener, &pfds, &fd_count, &fd_size);
struct user* temp = get_user(userlist,newfd);
char notify[128];
snprintf(notify, sizeof(notify),"{%s,%d,%d,%d}",
temp->username,temp->fd,temp->partner,4);
snprintf(buf, sizeof(buf),"%s connected\n", temp->username);
for (int j = 0; j < fd_count; j++) {
int dest_fd = pfds[j].fd;
if (dest_fd != listener && dest_fd != newfd) {
send(dest_fd, notify, strlen(notify), 0);
send(dest_fd, buf, strlen(buf), 0);
}
}
continue;
}
// Existing client sending something
int sender_fd = pfds[i].fd;
int nbytes = recv(sender_fd, buf, sizeof(buf), 0);
if (nbytes <= 0) {
// -------------------------
// HANDLE DISCONNECT
// -------------------------
printf("socket %d disconnected\n", sender_fd);
// Find their user entry
struct user *temp = userlist;
while (temp && temp->fd != sender_fd) {
temp = temp->next;
}
if (temp) {
// Broadcast updated user to everyone
char notify[128];
snprintf(notify, sizeof(notify),"{%s,%d,%d,%d}",
temp->username,temp->fd,temp->partner,4);
snprintf(buf, sizeof(buf),"%s disconnected\n", temp->username);
for (int j = 0; j < fd_count; j++) {
int dest_fd = pfds[j].fd;
if (dest_fd != listener && dest_fd != sender_fd) {
send(dest_fd, notify, strlen(notify), 0);
send(dest_fd, buf, strlen(buf), 0);
}
}
if(temp->partner != 0){
struct user* curr = get_user(userlist,temp->partner);
curr->status = 1;
curr->partner = 0;
}
}
// Remove from poll list
removeUser(userlist,sender_fd);
close(sender_fd);
del_from_pfds(pfds, i, &fd_count);
i--; // IMPORTANT: adjust index because pfds shifted
}
else {
// -------------------------
// NORMAL MESSAGE RECV
// -------------------------
// Broadcast buf to all others
//if its a private chat request we need to send that to the partner
buf[nbytes] = '\0';
int found = 0;
for(int i=0;istatus != 3){
for (int j = 0; j < fd_count; j++) {
int dest_fd = pfds[j].fd;
struct user* reciever = get_user(userlist,dest_fd);
if(reciever->partner == 0){
if (dest_fd != listener && dest_fd != sender_fd) {
if (send(dest_fd, msg, strlen(msg), 0) == -1) {
perror("send");
}
}
}
}
}
else{
if (send(sender->partner, msg, strlen(msg), 0) == -1) {
perror("send");
}
}
}
}
}
}
}
return 0;
}