static ssize_t network_read_line(struct iio_context_pdata *pdata, int desc, char *dst, size_t len) { size_t i; #ifdef __linux__ ssize_t ret; /* First read from the socket without advancing the read offset */ ret = recv(desc, dst, len, MSG_PEEK); if (ret < 0) return ret; /* Lookup for the trailing \n */ for (i = 0; i < (size_t) ret && dst[i] != '\n'; i++); /* No \n found? Just garbage data */ if (i == (size_t) ret) return -EIO; /* Advance the read offset to the byte following the \n */ return recv(desc, dst, i + 1, MSG_TRUNC); #else bool found = false; for (i = 0; i < len - 1; i++) { ssize_t ret = network_read_data(pdata, desc, dst + i, 1); if (ret < 0) return ret; if (dst[i] != '\n') found = true; else if (found) break; } dst[i] = '\0'; return (ssize_t) i; #endif }
// client reader int voicechat_ascent_socket_read_handler(network_socket *s, int act) { ascent_socket * mysock = (ascent_socket*)s->miscdata; uint16 opcode; uint16 len; int readcount; ascent_packet * pck; if( s->miscdata == NULL ) return -1; if( act == IOEVENT_ERROR ) { ascentsocket_free(mysock); return -1; // network code will clean up s pointer } readcount = network_read_data(s, &mysock->read_buf[mysock->read_buf_len], mysock->read_buf_sz - mysock->read_buf_len, NULL); if( readcount <= 0 ) { log_write(DEBUG, "ascent socket %u failed reading. probably dead.", s->fd); // channel_delete_by_owner(mysock); ascentsocket_free(mysock); return -1; } mysock->read_buf_len += readcount; // read packetz, munch munch gobble gobble for(;;) { if( mysock->read_buf_len < 4 ) { // size of the header. // packet must have been fragmented something nasty :P //printf("no full packet\n"); break; } // got a full header, lets pull the details opcode = *(uint16*)&mysock->read_buf[0]; len = *(uint16*)&mysock->read_buf[2]; // do we have the full packet? if( mysock->read_buf_len < (len + 2) ) { // wait for the full packet //printf("no full packet 2\n"); break; } // create ascentpacket structure pck = ascentpacket_create(opcode, len); memcpy(pck->buffer, mysock->read_buf+4, len); mysock->read_buf_len -= 4; mysock->read_buf_len -= len; // move the buffer bytes back if( mysock->read_buf_len != 0 ) memmove(mysock->read_buf, &mysock->read_buf[len+4], mysock->read_buf_len); // execute the handler if( opcode >= VOICECHAT_NUM_OPCODES ) { log_write(ERROR, "Voicechat client with fd %u sent an invalid opcode (%u)", mysock->sock->fd, opcode); } else { // find and execute the handler if( vc_handler_table[opcode] == NULL ) log_write(ERROR, "Voicechat client with fd %u sent an unhandled opcode (%u)", mysock->sock->fd, opcode); else vc_handler_table[opcode](mysock, pck); } // free the packet ascentpacket_free(pck); } return 0; }
int voicechat_client_socket_read_handler(network_socket *s, int act) { struct sockaddr_in read_address; char buffer[10000] = {0}; // people needing a bigger buffer, again can go to hell int bytes; uint16 channel_id; uint8 user_id; int i; voice_channel * chn; voice_channel_member * memb; if( act == IOEVENT_ERROR ) { log_write(ERROR, "UDP Socket read an error!"); return 0; } if( (bytes = network_read_data(s, buffer, 10000, (struct sockaddr*)&read_address)) < 0 ) { log_write(ERROR, "UDP socket read error bytes!"); return 0; } log_write(DEBUG, "udp socket got %d bytes from address %s", bytes, inet_ntoa(read_address.sin_addr)); channel_id = *(uint16*)(&buffer[5]); user_id = buffer[4]; chn = voice_channel_get((int)channel_id); log_write(DEBUG, "channel %u userid %u", (int)channel_id, (int)user_id); if( chn == NULL ) { log_write(ERROR, "udp client sent invalid voice channel."); return 0; } if( user_id >= chn->member_slots ) { log_write(ERROR, "udp client sent out of range user id."); return 0; } memb = &chn->members[user_id]; // client initial packet check if( bytes == 7 ) { if( memb->used && memcmp(&memb->client_address, &read_address, sizeof(struct sockaddr)) ) { log_write(ERROR, "udp client is sending a different read address than it should be. desync maybe?"); } memcpy(&memb->client_address, &read_address, sizeof(struct sockaddr)); //printf("client %u address set to %s\n", (int)user_id, inet_ntoa(chn->members[user_id].client_address.sin_addr)); memb->used = 1; } else { // distribute the packet for( i = 0; i < chn->member_slots; ++i ) { if( i == user_id || !chn->members[i].used || !chn->members[i].active ) continue; // don't send to yourself :P //printf("writing to client %u address %s\n", i, inet_ntoa(chn->members[i].client_address.sin_addr)); if( network_write_data( s, buffer, bytes, (struct sockaddr*)&chn->members[i].client_address ) < 0 ) { log_write(ERROR, "network_write_data to UDP client %s failed.", inet_ntoa(chn->members[i].client_address.sin_addr)); } } } return 0; }