//when you need to handle a join reply, use the params join_ip and join_port //otherwise, join_ip=0 and join_port=-1 void peer_list(unsigned int join_ip, short join_port, unsigned int room){ //create payload for join and update replies struct peer *s; int num_in_room = 0; for(s=peers; s != NULL; s=(peer *)s->hh.next){ if(s->room==room){ num_in_room = num_in_room+1; } } struct sockaddr_in list[num_in_room]; int a = 0; for(s=peers; s != NULL; s=(peer *)s->hh.next){ if(s->room==room){ unsigned int peer_ip = get_ip(s->ip_and_port); short peer_port = get_port(s->ip_and_port); struct sockaddr_in peer_info = get_sockaddr_in(peer_ip, peer_port); sockaddr_in* peer_info_ptr = &peer_info; memcpy((sockaddr_in*)&list[a], peer_info_ptr, sizeof(peer_info)); a=a+1; } } packet update_pkt; update_pkt.header.type = 'u'; update_pkt.header.error = '\0'; update_pkt.header.payload_length = num_in_room * sizeof(struct sockaddr_in); memcpy(update_pkt.payload, list, num_in_room * sizeof(struct sockaddr_in)); for(s=peers; s != NULL; s=(peer *)s->hh.next){ if(s->room==room){ unsigned int peer_ip = get_ip(s->ip_and_port); short peer_port = get_port(s->ip_and_port); if(join_port!=-1 and join_ip!=0 and peer_ip == join_ip and peer_port==join_port){ //send join packet join_pkt; join_pkt.header.type = 'j'; join_pkt.header.error = '\0'; join_pkt.header.room = room; join_pkt.header.payload_length = num_in_room * sizeof(struct sockaddr_in); memcpy(join_pkt.payload, list, num_in_room * sizeof(struct sockaddr_in)); struct sockaddr_in peer_addr = get_sockaddr_in(peer_ip, peer_port); int status = sendto(sock, &join_pkt, sizeof(join_pkt), 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr)); if (status == -1) { pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s\n", "error - error sending packet to peer"); pthread_mutex_unlock(&stdout_lock); } }else{ struct sockaddr_in peer_addr = get_sockaddr_in(peer_ip, peer_port); int status = sendto(sock, &update_pkt, sizeof(update_pkt), 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr)); if (status == -1) { pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s\n", "error - error sending packet to peer"); pthread_mutex_unlock(&stdout_lock); } } } } }
void peer_leave(unsigned int ip, short port){ char ip_port[20]; memset(ip_port, 0, sizeof(ip_port)); char* ip_and_port_format = (char *)"%d:%d"; sprintf(ip_port, ip_and_port_format, ip, port); struct peer *s; HASH_FIND_STR(peers, ip_port, s); if(s!=NULL){ unsigned int left_room = s->room; pthread_mutex_lock(&peers_lock); HASH_DEL( peers, s); free(s); pthread_mutex_unlock(&peers_lock); pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s left %d\n", ip_port, left_room); pthread_mutex_unlock(&stdout_lock); packet pkt; pkt.header.type = 'l'; pkt.header.error = '\0'; pkt.header.payload_length = 0; struct sockaddr_in peer_addr = get_sockaddr_in(ip, port); int status = sendto(sock, &pkt, sizeof(pkt.header), 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr)); if (status == -1) { pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s\n", "error - error sending packet to peer"); pthread_mutex_unlock(&stdout_lock); } peer_list(0, -1, left_room); }else{ send_error(ip, port, 'l', 'e'); } }
/* * udp connect do not real connect * only create a socket ! */ nesocket_t ne_socket_udp_connect(NEINT8 *host_name, NEINT16 port,SOCKADDR_IN *out_addr) { nesocket_t conn_sock ; if(out_addr) get_sockaddr_in(host_name, port, out_addr) ; conn_sock = socket(AF_INET, SOCK_DGRAM, 0); /* * to realizing p2p do not use system call 'bind' and 'connect' */ return conn_sock ; }
void send_error(unsigned int ip, short port, char type, char error){ packet pkt; pkt.header.type = type; pkt.header.error = error; pkt.header.payload_length = 0; struct sockaddr_in peer_addr = get_sockaddr_in(ip, port); int status = sendto(sock, &pkt, sizeof(pkt.header), 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr)); if (status == -1) { pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s\n", "error - error sending packet to peer"); pthread_mutex_unlock(&stdout_lock); } }
/* connect to server * @out put address of remote host * return -1 on error else return socket fd */ nesocket_t ne_socket_tcp_connect(NEINT8 *host_name, NEINT16 port,SOCKADDR_IN *out_addr) { nesocket_t conn_sock ; SOCKADDR_IN their_addr = {0} ; if(-1==get_sockaddr_in(host_name, port, &their_addr) ) { return -1 ; } conn_sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if(-1==conn_sock) return -1; if(-1==connect(conn_sock,(LPSOCKADDR)&their_addr, sizeof(struct sockaddr)) ) { close(conn_sock); return -1 ; } if(out_addr) memcpy((void*)out_addr, (void*)&their_addr, sizeof(their_addr)) ; return conn_sock; }
//mark all peers "dead" and send pings void send_pings(){ struct peer *s; for(s=peers; s != NULL; s=(struct peer *)s->hh.next){ //mark dead pthread_mutex_lock(&peers_lock); s->alive = 0; pthread_mutex_unlock(&peers_lock); //send ping unsigned int peer_ip = get_ip(s->ip_and_port); short peer_port = get_port(s->ip_and_port); packet pkt; pkt.header.type = 'p'; pkt.header.error = '\0'; pkt.header.payload_length = 0; struct sockaddr_in peer_addr = get_sockaddr_in(peer_ip, peer_port); int status = sendto(ping_sock, &pkt, sizeof(pkt.header), 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr)); if (status == -1) { pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s\n", "error - error sending packet to peer"); pthread_mutex_unlock(&stdout_lock); } } }
void proxy(const char* message, int fd) { const int just_say_no = 1; char buffer[8192]; struct sockaddr_in pin; int sd, i, pid; char *text = find(message, "Host:"); printf("text [%s]\n", text); char splited[3][256]; if (text == NULL) { error("Error: NULL message."); } int n = split(text, " ", splited); free(text); if (splited[1] == NULL) { error("Error: invalid URL."); } for (i = 0; i < n; i++) { printf("%s\n", splited[i]); } pin = get_sockaddr_in(splited[1], HTTPPORT); if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { error("Error on socket"); } /* connect to PORT on HOST */ if (connect(sd, (struct sockaddr *) &pin, sizeof(pin)) == -1) { error("Error on connect"); } setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *) &just_say_no, sizeof(just_say_no)); /* send a message to the server PORT on machine HOST */ if (send(sd, message, strlen(message), 0) == -1) { error("Error on send"); } i = 0; ssize_t rc; ssize_t amt; ssize_t offset; while ((rc = recv(sd, buffer, sizeof(buffer), 0)) > 0) { if (rc <= 0) { if (rc == 0) break; if (errno == EINTR || errno == EAGAIN) continue; error("read error"); } offset = 0; amt = rc; pid = fork(); if (pid < 0) { error("Error on fork"); } if (pid == 0) { while (amt) { rc = send(fd, buffer + offset, amt, 0); if (rc < 0) { if (errno == EINTR || errno == EAGAIN) continue; error("write error"); } offset += rc; amt -= rc; } } else { close(sd); } } }
void room_list(unsigned int ip, short port){ int number_of_rooms = get_total_num_rooms(); unsigned int room_indexed[number_of_rooms]; memset(room_indexed, 0, number_of_rooms * sizeof(room_indexed[0])); unsigned int room_nums[number_of_rooms]; memset(room_nums, 0, number_of_rooms * sizeof(room_nums[0])); int room_stats[number_of_rooms]; memset(room_stats, 0, number_of_rooms * sizeof(room_stats[0])); struct peer *s; int max_occupants=0; unsigned int max_room_number =0; int num_rooms_indexed = 0; for(s=peers; s != NULL; s=(peer *)s->hh.next){ int room_index=-1; unsigned int a; for(a=0; a<sizeof(room_nums)/sizeof(room_nums[0]); a++){ if(room_nums[a]==s->room){ room_index=a; break; } } if(room_indexed[room_index]==0){ room_index = num_rooms_indexed; room_nums[room_index] = s->room; room_stats[room_index] = 1; room_indexed[room_index]= 1; num_rooms_indexed = num_rooms_indexed+1; }else{ room_stats[room_index] = room_stats[room_index]+1; } if(room_stats[room_index]>max_occupants){ max_occupants=room_stats[room_index]; } if(room_nums[room_index]>max_room_number){ max_room_number=room_nums[room_index]; } } int max_room_num_len; if(max_room_number==0){ max_room_num_len=1; }else{ max_room_num_len=(int)floor(log10((float)max_room_number)) + 1; } int max_room_size_len = (int)floor(log10((float)MAX_ROOM_SIZE)) + 1; int max_num_room_len = (int)floor(log10((float)max_occupants)) + 1; char *list_entry_format = (char *)"room: %d - %d/%d\n"; int list_entry_size = max_room_num_len+max_num_room_len+max_room_size_len+strlen(list_entry_format); int list_size = max_num_room_len*list_entry_size; char *list_entry = (char *)malloc(list_entry_size); char *list = (char *)malloc(list_size); unsigned int i; char *list_i = list; for(i=0; i<sizeof(room_stats)/sizeof(room_stats[0]); i++){ sprintf(list_entry, list_entry_format, room_nums[i], room_stats[i], MAX_ROOM_SIZE); strcpy(list_i, list_entry); list_i += strlen(list_entry); } if(number_of_rooms==0){ list=(char*)"There are no chatrooms\n"; } pthread_mutex_lock(&stdout_lock); fprintf(stderr, "room list\n%s\n", list); pthread_mutex_unlock(&stdout_lock); packet pkt; pkt.header.type = 'r'; pkt.header.error = '\0'; pkt.header.payload_length = list_size; strcpy(pkt.payload, list); struct sockaddr_in peer_addr = get_sockaddr_in(ip, port); int status = sendto(sock, &pkt, sizeof(pkt), 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr)); if (status == -1) { pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s\n", "error - error sending packet to peer"); pthread_mutex_unlock(&stdout_lock); } }
void peer_create_room(unsigned int ip, short port){ //check if room limit reached int number_of_rooms = get_total_num_rooms(); if(number_of_rooms>=MAX_NUM_ROOMS){ send_error(ip, port, 'c', 'o'); pthread_mutex_lock(&stdout_lock); fprintf(stderr, "Peer create room failed - max number of rooms reached.\n"); pthread_mutex_unlock(&stdout_lock); return; } //get a room number struct peer *s; int room_taken = 0; unsigned int room; for(room=1; room<MAX_NUM_ROOMS*2; room++){ for(s=peers; s != NULL; s=(struct peer *)s->hh.next){ if(s->room == room){ room_taken=1; break; } } if(room_taken==0){ break; }else{ room_taken=0; } } //create entry struct peer *new_peer; new_peer = (struct peer *)malloc(sizeof(struct peer)); char* ip_and_port_format = (char *)"%d:%d"; sprintf(new_peer->ip_and_port, ip_and_port_format, ip, port); new_peer->room = room; new_peer->alive = 1; //check if peer in a room HASH_FIND_STR(peers, (new_peer->ip_and_port), s); if(s!=NULL){ pthread_mutex_lock(&stdout_lock); fprintf(stderr, "Peer create room failed - already in a room.\n"); pthread_mutex_unlock(&stdout_lock); send_error(ip, port, 'c', 'e'); }else{ pthread_mutex_lock(&peers_lock); HASH_ADD_STR( peers, ip_and_port, new_peer ); //create room - add peer pthread_mutex_unlock(&peers_lock); pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s created %d\n", new_peer->ip_and_port, room); pthread_mutex_unlock(&stdout_lock); packet pkt; pkt.header.type = 'c'; pkt.header.error = '\0'; pkt.header.room = room; pkt.header.payload_length = 0; struct sockaddr_in peer_addr = get_sockaddr_in(ip, port); int status = sendto(sock, &pkt, sizeof(pkt.header), 0, (struct sockaddr *)&peer_addr, sizeof(peer_addr)); if (status == -1) { pthread_mutex_lock(&stdout_lock); fprintf(stderr, "%s\n", "error - error sending packet to peer"); pthread_mutex_unlock(&stdout_lock); } } }