测试多插几个音乐
看看不同音乐会不会相互影响这是第一个
这是第二个
这是第三个
#在这里输入代码(从下一行开始,不要删除我...)
/* A simple server in the internet domain using TCP
The port number is passed as an argument */
/**
* server 主要进行请求的分发,接收到新的请求就把请求分发给route,
*/
#include "server.h"
#ifdef _WIN32
#pragma comment(lib,"libtox.dll.a")
#pragma comment(lib,"ws2_32.lib")
#pragma comment(lib,"jansson.lib")
#endif
/**
* Globals
*/
Tox *my_tox;
Queue *msg_task_queue; // 消息处队列
Queue *msg_rec_queue; //需要传递给node端的信息
Msg_listener_list *msg_listener_list = NULL;
uint8_t MODE = 0; // 0 req mode 1,server mode
uint8_t offline_count = 0;
// 队列等待条件锁
extern pthread_mutex_t msg_task_lock;
pthread_cond_t msg_task_cond = PTHREAD_COND_INITIALIZER;
const uint8_t *target_ip; // 远端连接目标IP
uint32_t target_port; // 远端连接目标端口
const uint8_t *target_id; // 远程目标ADDRESS
uint32_t local_port; //本地端口
// FRIEND NUMBER
uint32_t FRIEND_NUM = 0;
// flags
int32_t init_over_flag = 0;
int32_t init_req_flag = 0;
// local sockets
local_socks_list *msocks_list = NULL;
uint32_t local_socksfd = 0;
//debug
int previous = -1;
void error(const char *msg)
{
perror(msg);
exit(1);
}
// typedef struct accept_req_params{
// Tox *m;
// const uint8_t *id;
// Msg_listener_list *msg_listener_list;
// uint32_t sockfd;
//
// }accept_req_params;
// void *accept_req_work(void *mparms){
// accept_req_params *parms = (accept_req_params *)mparms;
// accept_connect(parms->m,parms->id,parms->msg_listener_list,parms->sockfd);
// }
void friend_request(Tox *messenger, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) {
//接受請求
// printf("req received\n");
// uint8_t *str = (uint8_t *)malloc(sizeof(uint8_t)*(TOX_CLIENT_ID_SIZE*2+1));
// hex_bin_to_string(public_key,TOX_CLIENT_ID_SIZE,str);
// // start a new thread to init new connection
//
// pthread_t *accept_req_thread;
// accept_req_thread = (pthread_t *)malloc(sizeof(pthread_t));
// accept_req_params *req_parms = (accept_req_params *)malloc(sizeof(accept_req_params));
// req_parms->m = my_tox;
// req_parms->id = str;
// req_parms->msg_listener_list = msg_listener_list;
// req_parms->sockfd = local_socksfd;
//
// int iret1 = pthread_create( accept_req_thread, NULL,accept_req_work,req_parms);
// if(iret1){
// exit(EXIT_FAILURE);
// }else{
// // write_local_message(local_socksfd,"PROCESSING FRIEND REQ");
// }
}
void friend_message(Tox *m, int32_t friendnumber, const uint8_t *bin, uint16_t length, void *userdata) {
uint8_t client_id_bin[TOX_CLIENT_ID_SIZE+1];
uint8_t client_id_str[TOX_CLIENT_ID_SIZE*2+1];
tox_get_client_id(m,friendnumber,client_id_bin);
hex_bin_to_string(client_id_bin,TOX_CLIENT_ID_SIZE,client_id_str);
// 添加消息觸發器
trigger_msg_listener(msg_listener_list,bin,client_id_str);
if(MODE == 1){
}
// 请求者模式
if(MODE == 0){
if(strcmp(bin,"HANDSHAKE") == 0){
printf("HANDSHAKE RECEIVED\n");
return;
}
// parse message
uint8_t *uuid = (uint8_t *)malloc(sizeof(uint8_t)*UUID_LENGTH);
uint8_t *cmd = (uint8_t *)malloc(sizeof(uint8_t)*128);
uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t)*MY_MESSAGE_LENGTH);
uint32_t *length = (uint32_t *)malloc(sizeof(uint32_t));
unpack_msg_bin(bin, uuid, cmd, data, length);
if(strcmp(cmd,"UNKNOWN_CMD") == 0){
}else if(strcmp(cmd,"RAW_DATA") == 0){
on_remote_data_received(uuid, data, *length, client_id_bin);
}else{
printf("CMD:%s\n",cmd);
if(strcmp(cmd,"CLOSE_SOCK") == 0){
int32_t sockfd = get_local_socks(msocks_list,uuid);
close_local_socks(msocks_list,sockfd);
}
if(strcmp(cmd, "CREATE_SOCK_SUCCESS") == 0){
int32_t sockfd = get_local_socks(msocks_list,uuid);
pthread_t new_sock_thread;
uint32_t *msockfd = malloc(sizeof(uint32_t));
*msockfd = sockfd;
pthread_create(&new_sock_thread, NULL, on_remote_sock_created, msockfd);
}
}
// free data
free(uuid);
free(cmd);
free(data);
free(length);
}
}
void write_file(Tox *messenger, int32_t friendnumber, uint8_t filenumber,const uint8_t *data, uint16_t length, void *userdata) {
}
void file_print_control(Tox *messenger, int friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t control_type, const uint8_t *data, uint16_t length, void *userdata) {
}
void file_request_accept(Tox *messenger, int friendnumber, uint8_t filenumber, uint64_t filesize,const uint8_t *filename, uint16_t filename_length, void *userdata) {
}
void on_connectionchange(Tox *m, int32_t friendnumber, uint8_t status, void *userdata){
}
static Tox *init_tox()
{
Tox *m = tox_new(1);
if (m == NULL) {
// fprintf(stderr, "IPv6 didn't initialize, trying IPv4\n");
m = tox_new(0);
}
if (m ==NULL)
// fprintf(stderr, "Forcing IPv4 connection\n");
/* Callbacks */
tox_callback_connection_status(m, on_connectionchange, NULL);
//tox_callback_typing_change(m, on_typing_change, NULL);
tox_callback_friend_request(m, friend_request, NULL);
tox_callback_friend_message(m, friend_message, NULL);
//tox_callback_name_change(m, on_nickchange, NULL);
//tox_callback_user_status(m, on_statuschange, NULL);
//tox_callback_status_message(m, on_statusmessagechange, NULL);
//tox_callback_friend_action(m, on_action, NULL);
//tox_callback_group_invite(m, on_groupinvite, NULL);
//tox_callback_group_message(m, on_groupmessage, NULL);
//tox_callback_group_action(m, on_groupaction, NULL);
//tox_callback_group_namelist_change(m, on_group_namelistchange, NULL);
tox_callback_file_send_request(m, file_request_accept, NULL);
tox_callback_file_control(m, file_print_control, NULL);
tox_callback_file_data(m, write_file, NULL);
tox_set_name(m, MY_NAME, strlen(MY_NAME)); // Sets the username
return m;
}
int init_tox_connection(Tox *m)
{
uint8_t pub_key[TOX_FRIEND_ADDRESS_SIZE];
hex_string_to_bin(pub_key, BOOTSTRAP_KEY);
int res = tox_bootstrap_from_address(m, BOOTSTRAP_ADDRESS, 0, htons(BOOTSTRAP_PORT), pub_key);
if (!res) {
exit(1);
}
return 0;
}
void *tox_works(void *a){
// do tox loop
time_t timestamp0 = time(NULL);
int on = 0;
while (1) {
if (on == 0) {
if (tox_isconnected(my_tox)) {
on = 1;
} else {
time_t timestamp1 = time(NULL);
if (timestamp0 + 10 < timestamp1) {
timestamp0 = timestamp1;
init_tox_connection(my_tox);
}
}
}
tox_do(my_tox);
if(msg_task_queue->size != 0){
send_data_remote();
}else{
#ifdef _WIN32
Sleep(4);
#else
usleep(4000);
#endif
}
}
}
void intHandler(int dummy) {
store_data(my_tox);
#ifdef _WIN32
WSACleanup();
#endif
printf("EXITING...\n");
exit(EXIT_SUCCESS);
}
#ifdef _WIN32
int32_t init_local_sock_serv(uint32_t local_port){
int32_t iServerSock;
struct sockaddr_in ServerAddr;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(1, 1), &WSAData)){
printf("initializationing error!\n");
exit(0);
}
if((iServerSock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
printf("create socket failed\n");
exit(0);
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(local_port);//监视的端口号
ServerAddr.sin_addr.s_addr = INADDR_ANY;//本地IP
memset(& (ServerAddr.sin_zero), 0, sizeof(ServerAddr.sin_zero));
if(bind(iServerSock, (struct sockaddr *)&ServerAddr, sizeof(struct sockaddr)) == -1){
printf("bind failed!\n");
exit(0);
}
if(listen(iServerSock, 5) == -1){
printf("listen failed!\n");
exit(0);
}
return iServerSock;
}
int init_local_sock(int local_port){
int iClientSock;
struct sockaddr_in ServerAddr;
WSADATA WSAData;
if(WSAStartup(MAKEWORD(1, 1), &WSAData)){
printf("initializationing error!\n");
exit(0);
}
if((iClientSock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET){
printf("create socket failed!\n");
exit(0);
}
ServerAddr.sin_family = AF_INET;
ServerAddr.sin_port = htons(local_port);
ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(&(ServerAddr.sin_zero), 0, sizeof(ServerAddr.sin_zero));
if(connect(iClientSock, (struct sockaddr *) & ServerAddr, sizeof(struct sockaddr)) == -1){
printf("connect failed");
exit(0);
}
return iClientSock;
}
#else
int32_t init_local_sock(uint32_t local_port){
struct sockaddr_in serv_addr;
struct hostent *server;
int32_t sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
server = gethostbyname("127.0.0.1");
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(local_port);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");
return sockfd;
}
int32_t init_local_sock_serv(uint32_t local_port){
int sockfd;
struct sockaddr_in serv_addr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket");
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(local_port);
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
error("ERROR on binding");
listen(sockfd,5);
return sockfd;
}
#endif
int32_t readCSock(uint32_t sockfd,uint8_t *buf,uint32_t length){
#ifdef _WIN32
return recv(sockfd, buf, length, 0);
#else
return read(sockfd, buf, length);
#endif
}
int32_t writeCSock(uint32_t sockfd, const uint8_t *buf, uint32_t length){
#ifdef _WIN32
return send(sockfd, buf, length, 0);
#else
return write(sockfd,buf,length);
#endif
}
/**
* add data to remote message queue
* this func may block if current message queue is not available
* data format
* {
* target_id: target to send
* uuid: sock uuid
* data: raw data <SOCK_BUF_SIZE or less>
* cmd: can be null when no cmd is to send
* }
*
*/
void write_data_remote(const uint8_t *uuid, const uint8_t* cmd, const uint8_t *data, const uint32_t length){
// pack msg to bin
uint8_t *msg_bin = (uint8_t *)malloc(sizeof(uint8_t)*MY_MESSAGE_LENGTH);
pack_msg_bin(msg_bin, uuid, cmd, data, length);
// add msg to message queue
MSGTask *newTask = (MSGTask *)malloc(sizeof(MSGTask));
uint8_t *target_addr_bin = (uint8_t *)malloc(sizeof(uint8_t)*TOX_FRIEND_ADDRESS_SIZE);
hex_string_to_bin(target_addr_bin, target_id);
newTask->target_addr_bin = target_addr_bin;
newTask->msg = msg_bin;
pthread_mutex_lock(&msg_task_lock);
while ((msg_task_queue->size) >= MAX_MSG_CACHE){
pthread_cond_wait(&msg_task_cond, &msg_task_lock);
};
// enter queue
Enqueue(msg_task_queue, newTask);
if((msg_task_queue->size) < MAX_MSG_CACHE)
pthread_cond_broadcast(&msg_task_cond);
pthread_mutex_unlock(&msg_task_lock);
// free space
free(msg_bin);
free(target_addr_bin);
free(newTask);
}
/*
void debug_msg_bin(uint8_t *msg_bin){
if(msg_bin[UUID_LENGTH] != 0)return;
uint8_t hight_byte = msg_bin[UUID_LENGTH+CMD_LENGTH];
uint8_t low_byte = msg_bin[UUID_LENGTH+CMD_LENGTH + 1];
uint32_t length = hight_byte*256 +low_byte;
uint8_t data[length];
int i=0;
for(i=0;i<length;i++){
data[i] = msg_bin[i + UUID_LENGTH + CMD_LENGTH + MESSAGE_LENGTH_BYTE];
}
debug_data(data,length);
}*/
/**
* read message from remote message queue, and send to remote
* this will only send one message in the message queue
* and write_data_remote will be block at the same time
*/
void send_data_remote(){
MSGTask *mTask = front(msg_task_queue); // 开始处理
int friend_num = tox_get_friend_number(my_tox,mTask->target_addr_bin);
int res = -1;
int retry_count = 0;
//debug_msg_bin(bin);
while(res <=0 && retry_count <5){
res = tox_send_message(my_tox,friend_num,mTask->msg,MY_MESSAGE_LENGTH);
retry_count += 1;
}
if(retry_count < 5){
Dequeue(msg_task_queue);
pthread_cond_broadcast(&msg_task_cond);
}else{
// check target online status
if(tox_get_friend_connection_status(my_tox,friend_num) != 1){
// target offline
Dequeue(msg_task_queue);
pthread_cond_broadcast(&msg_task_cond);
// unpack msg to get uuid
uint8_t *uuid = (uint8_t *)malloc(sizeof(uint8_t)*UUID_LENGTH+1);
memset(uuid,'\0',UUID_LENGTH+1);
uint8_t *cmd = (uint8_t *)malloc(sizeof(uint8_t)*128);
uint8_t *data = (uint8_t *)malloc(sizeof(uint8_t)*MY_MESSAGE_LENGTH);
uint32_t *length = (uint32_t *)malloc(sizeof(uint32_t));
unpack_msg_bin(mTask->msg, uuid, cmd, data, length);
// get socket fd by uuid
int32_t sockfd = get_local_socks(msocks_list,uuid);
// close socket
close_local_socks(msocks_list,sockfd);
free(uuid);
free(cmd);
free(data);
free(length);
printf("target is offline. ******************************************************\n");
printf("status %d\n", tox_get_friend_connection_status(my_tox,friend_num));
printf("friend num %d\n", friend_num);
//exit(1);
}
}
}
void debug_data(const uint8_t *data,uint32_t length){
uint32_t i =0;
if(previous != -1){
if(data[0] != previous +1 && data[0] != 0){
printf("%d,%d\n",previous,data[0]);
printf("DATA ERROR 1\n");
exit(1);
}
}
for(i=0;i<length-1;i++){
if(data[i+1] != data[i]+1 && data[i+1] !=0){
printf("%d,%d\n",data[i],data[i+1]);
printf("DATA ERROR\n");
exit(1);
}
}
previous = data[length-1];
}
/**
* this func will be called immediately after local data received
* wrap data in proper format
* {
* uuid
* data
* }
*/
void on_local_data_received(uint8_t *data, uint32_t length,uint32_t sockfd){
uint8_t uuid[UUID_LENGTH+1];
get_local_socks_uuid(msocks_list,sockfd,uuid);
if(uuid[0] == '\0'){
printf("on_local_data_received error\n");// Bug: this is still known
return;
}
write_data_remote(uuid,NULL,data,length);
}
/**
* this func will be called immediately after remote data received
* NOTE: remote data is not remote message. it's remote message with fixed format
* {
* uuid
* data
* cmd
* }
*/
void on_remote_data_received(const uint8_t *uuid, const uint8_t *data, const uint32_t length, const uint8_t *client_id_bin){
// get sockfd from uuid
int32_t sockfd = get_local_socks(msocks_list,uuid);
// send data to target socket
if(sockfd != 0){
// record found
writeCSock(sockfd, data, length);
}else{
// socket might be closed
printf("INVALID SOCKET, CLOSE IT\n");
close_remote_socket(uuid,client_id_bin);
}
}
/**
* close remote socket
*/
void close_remote_socket(const uint8_t *uuid, const uint8_t *client_id_bin){
if(uuid[0] == '\0'){
printf("close_remote_socket error\n");
}
write_data_remote(uuid,"CLOSE_SOCK","",strlen(""));
}
void create_remote_socket(const uint8_t *uuid, const uint8_t *client_id_bin,const uint8_t *target_ip, uint32_t target_port){
json_t *target_port_json = json_pack("i",target_port);
json_t *target_ip_json = json_pack("s",target_ip);
json_t *data = json_object();
json_object_set(data,"target_ip",target_ip_json);
json_object_set(data,"target_port",target_port_json);
uint8_t *data_str = json_dumps(data,JSON_INDENT(4));
if(uuid[0] == '\0'){
printf("create_remote_socket error\n");
exit(1);
}
write_data_remote(uuid,"CREATE_SOCK",data_str,strlen(data_str));
// release data
json_decref(target_port_json);
json_decref(target_ip_json);
json_decref(data);
free(data_str);
}
void *on_remote_sock_created(void *msockfd){
uint32_t sockfd = *((uint32_t *)msockfd);
uint8_t *target_addr_bin = (uint8_t *)malloc(sizeof(uint8_t)*TOX_FRIEND_ADDRESS_SIZE);
hex_string_to_bin(target_addr_bin,target_id);
uint8_t uuid[UUID_LENGTH+1];
get_local_socks_uuid(msocks_list,sockfd,uuid);
printf("uuid: %s\n",uuid);
printf("socketfd: %d\n",sockfd);
uint8_t buf[SOCK_BUF_SIZE];
int length = 1;
while(length > 0){
memset(buf,0,SOCK_BUF_SIZE);
length = readCSock(sockfd,buf,SOCK_BUF_SIZE-1);
if(length > 0){
on_local_data_received(buf,length,sockfd);
}
}
// read data error
// close remote and local sock
printf("uuid: %s\n", uuid);
printf("socketfd: %d\n", sockfd);
if(get_local_socks(msocks_list, uuid) != 0){
close_remote_socket(uuid,target_addr_bin);// 从本地发起的关闭
}else{
// closed by remote before create success send
if(uuid[0] == '\0'){
//exit(0);// maybe local socket has been closed
printf("closed by local before create socket received\n");
}
}
close_local_socks(msocks_list, sockfd);
free(target_addr_bin);
free(msockfd);
return NULL;
}
int main(int argc, char *argv[])
{
// 添加系统事件监听
signal(SIGINT, intHandler);
#ifndef _WIN32
signal(SIGPIPE, SIG_IGN);
#endif
my_tox = init_tox();
init_tox_connection(my_tox);
load_data(my_tox);
// 处理参数
if(argc >3){
local_port = atoi(argv[1]);
target_id = argv[2];
target_ip = argv[3];
target_port = atoi(argv[4]);
uint8_t my_address_bin[TOX_FRIEND_ADDRESS_SIZE+1];
uint8_t my_address_str[TOX_FRIEND_ADDRESS_SIZE*2+1];
tox_get_address(my_tox,my_address_bin);
hex_bin_to_string(my_address_bin,TOX_FRIEND_ADDRESS_SIZE,my_address_str);
printf("MYID:%s\n",my_address_str);
}else{
local_port = 9990 ;
target_id = "3E567CBCE8DA8A18ED3C30127ADB61D78AFA2D01B5CD12425C110E84F23AC365144CE2807378";
target_ip = "127.0.0.1";
target_port = 22;
/*target_id = NULL;
uint8_t my_address_bin[TOX_FRIEND_ADDRESS_SIZE];
uint8_t my_address_str[TOX_FRIEND_ADDRESS_SIZE*2];
tox_get_address(my_tox,my_address_bin);
hex_bin_to_string(my_address_bin,TOX_FRIEND_ADDRESS_SIZE,my_address_str);
printf("MYID:%s\n",my_address_str);*/
}
// 虛擬參數
// 初始化消息隊列
msg_task_queue = createQueue(MAX_MSG_CACHE); // 远程操作消息队列
// 開始tox線程
pthread_t tox_thread;
int iret1 = pthread_create( &tox_thread, NULL, tox_works,NULL);
if(iret1){
exit(EXIT_FAILURE);
}
// 初始化本地连接
local_socksfd = init_local_sock_serv(local_port);
// 等待tox成功連接
while(!tox_isconnected(my_tox)){
#ifdef _WIN32
Sleep(20);
#else
usleep(20000);
#endif
}
printf("TOXCORE:ONLINE\n");
printf("SERVER:LISTEN ON %d\n",local_port);
// 開始準備連接
if(target_id != NULL){
// 進入請求者模式
int res = init_connect(my_tox,target_id,&msg_listener_list);
if(res == 402){
printf("CONNECT:OK\n");
}
else{
printf("CONNECT:ERROR\n");
}
}else{
// 進入服務者模式
MODE = 1;
}
// client mode
// create local tcp server
msocks_list = create_local_socks_list();
while(1){
struct sockaddr_in cli_addr;
uint32_t clilen = sizeof(cli_addr);
int32_t newsockfd = accept(local_socksfd,
(struct sockaddr *) &cli_addr,
&clilen);
if (newsockfd < 0){
printf("socket error\n");
}
else{
printf("accepted:%d\n", newsockfd);
// 发送创建远程端口指令
uint32_t sockfd = newsockfd;
uint8_t *target_addr_bin = (uint8_t *)malloc(sizeof(uint8_t)*TOX_FRIEND_ADDRESS_SIZE);
hex_string_to_bin(target_addr_bin,target_id);
add_local_socks(msocks_list,sockfd,target_addr_bin,target_ip,target_port);
// create remote socket
uint8_t uuid[UUID_LENGTH+1];
get_local_socks_uuid(msocks_list,sockfd,uuid);
create_remote_socket(uuid,target_addr_bin,target_ip,target_port);
free(target_addr_bin);
}
}
printf("EXITED\n");
return 0;
}