void init_turn_permission_map(turn_permission_map *map) { int i=0; (*map)=(turn_permission_map)turn_malloc(sizeof(turn_permission_info*)*TURN_PERMISSION_MAP_SIZE); for(i=0;i<TURN_PERMISSION_MAP_SIZE;i++) { (*map)[i]=NULL; } }
int turn_mutex_init_recursive(turn_mutex* mutex) { int ret = -1; if (mutex) { pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr) < 0) { perror("Cannot init mutex attr"); } else { if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) < 0) { perror("Cannot set type on mutex attr"); } else { mutex->mutex = turn_malloc(sizeof(pthread_mutex_t)); mutex->data = MAGIC_CODE; if ((ret = pthread_mutex_init((pthread_mutex_t*) mutex->mutex, &attr)) < 0) { perror("Cannot init mutex"); mutex->data = 0; turn_free(mutex->mutex,sizeof(pthread_mutex_t)); mutex->mutex = NULL; } } pthread_mutexattr_destroy(&attr); } } return ret; }
turnports* turnports_create(u16bits start, u16bits end) { if(start>end) return NULL; turnports* ret=(turnports*)turn_malloc(sizeof(turnports)); turnports_init(ret,start,end); return ret; }
int turn_mutex_init(turn_mutex* mutex) { if(mutex) { mutex->data=MAGIC_CODE; mutex->mutex=turn_malloc(sizeof(pthread_mutex_t)); pthread_mutex_init((pthread_mutex_t*)mutex->mutex,NULL); return 0; } else { return -1; } }
turnipports* turnipports_create(u16bits start, u16bits end) { turnipports *ret = (turnipports*) turn_malloc(sizeof(turnipports)); ret->ip_to_turnports_udp = ur_addr_map_create(0); ret->ip_to_turnports_tcp = ur_addr_map_create(0); ret->start = start; ret->end = end; TURN_MUTEX_INIT_RECURSIVE(&(ret->mutex)); return ret; }
turn_permission_info* allocation_add_permission(allocation *a, const ioa_addr* addr) { if(a && addr) { turn_permission_map map = a->addr_to_perm; turn_permission_info *elem=(turn_permission_info *)turn_malloc(sizeof(turn_permission_info)); ns_bzero(elem,sizeof(turn_permission_info)); elem->channels = ur_map_create(); addr_cpy(&elem->addr,addr); u32bits hash=addr_hash_no_port(addr); int fds=(int)(hash%TURN_PERMISSION_MAP_SIZE); elem->list.next=NULL; map[fds]=push_back_cilist(map[fds],elem); elem->owner = a; return elem; } else { return NULL; } }
static MONGO * get_mongodb_connection(void) { persistent_users_db_t * pud = get_persistent_users_db(); MONGO * mydbconnection = (MONGO *) pthread_getspecific(connection_key); if (!mydbconnection) { mongoc_init(); mongoc_log_set_handler(&mongo_logger, NULL); mydbconnection = (MONGO *) turn_malloc(sizeof(MONGO)); mydbconnection->uri = mongoc_uri_new(pud->userdb); if (!mydbconnection->uri) { TURN_LOG_FUNC( TURN_LOG_LEVEL_ERROR, "Cannot open parse MongoDB URI <%s>, connection string format error\n", pud->userdb); MongoFree(mydbconnection); mydbconnection = NULL; } else { mydbconnection->client = mongoc_client_new_from_uri( mydbconnection->uri); if (!mydbconnection->client) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot initialize MongoDB connection\n"); MongoFree(mydbconnection); mydbconnection = NULL; } else { mydbconnection->database = mongoc_uri_get_database( mydbconnection->uri); if (!mydbconnection->database) mydbconnection->database = MONGO_DEFAULT_DB; if(mydbconnection) { (void) pthread_setspecific(connection_key, mydbconnection); } TURN_LOG_FUNC( TURN_LOG_LEVEL_INFO, "Opened MongoDB URI <%s>\n", pud->userdb); } } } return mydbconnection; }
static server_type* init_server(int verbose, const char* ifname, char **local_addresses, size_t las, int port) { server_type* server=(server_type*)turn_malloc(sizeof(server_type)); if(!server) return server; ns_bzero(server,sizeof(server_type)); server->verbose=verbose; server->event_base = event_base_new(); while(las) { udp_create_server_socket(server, ifname, local_addresses[--las], port); udp_create_server_socket(server, ifname, local_addresses[las], port+1); } return server; }
tls_listener_relay_server_type* create_tls_listener_server(const char* ifname, const char *local_address, int port, int verbose, ioa_engine_handle e, ioa_engine_new_connection_event_handler send_socket, struct relay_server *relay_server) { tls_listener_relay_server_type* server = (tls_listener_relay_server_type*) turn_malloc(sizeof(tls_listener_relay_server_type)); ns_bzero(server, sizeof(tls_listener_relay_server_type)); if (init_server(server, ifname, local_address, port, verbose, e, send_socket, relay_server) < 0) { turn_free(server, sizeof(tls_listener_relay_server_type)); return NULL ; } else { return server; } }
tcp_connection *create_tcp_connection(u08bits server_id, allocation *a, stun_tid *tid, ioa_addr *peer_addr, int *err_code) { tcp_connection_list *tcl = &(a->tcl); while(tcl->next) { tcp_connection *otc = (tcp_connection*)(tcl->next); if(addr_eq(&(otc->peer_addr),peer_addr)) { *err_code = 446; return NULL; } tcl=tcl->next; } tcp_connection *tc = (tcp_connection*)turn_malloc(sizeof(tcp_connection)); ns_bzero(tc,sizeof(tcp_connection)); tcl->next = &(tc->list); addr_cpy(&(tc->peer_addr),peer_addr); if(tid) ns_bcopy(tid,&(tc->tid),sizeof(stun_tid)); tc->owner = a; set_new_tc_id(server_id, tc); return tc; }
ch_info* allocation_get_new_ch_info(allocation* a, u16bits chnum, ioa_addr* peer_addr) { turn_permission_info* tinfo = get_from_turn_permission_map(a->addr_to_perm, peer_addr); if (!tinfo) tinfo = allocation_add_permission(a, peer_addr); ch_info* chn = (ch_info*)turn_malloc(sizeof(ch_info)); ns_bzero(chn,sizeof(ch_info)); chn->chnum = chnum; chn->port = addr_get_port(peer_addr); addr_cpy(&(chn->peer_addr), peer_addr); chn->owner = tinfo; ur_map_put(a->channel_to_ch_info, chnum, chn); ur_map_put(tinfo->channels, (ur_map_key_type) addr_get_port(peer_addr), (ur_map_value_type) chn); return chn; }
static int udp_create_server_socket(server_type* server, const char* ifname, const char *local_address, int port) { FUNCSTART; if(!server) return -1; evutil_socket_t udp_fd = -1; ioa_addr *server_addr = (ioa_addr*)turn_malloc(sizeof(ioa_addr)); STRCPY(server->ifname,ifname); if(make_ioa_addr((const u08bits*)local_address, port, server_addr)<0) return -1; udp_fd = socket(server_addr->ss.ss_family, SOCK_DGRAM, 0); if (udp_fd < 0) { perror("socket"); return -1; } if(sock_bind_to_device(udp_fd, (unsigned char*)server->ifname)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO,"Cannot bind udp server socket to device %s\n",server->ifname); } set_sock_buf_size(udp_fd,UR_SERVER_SOCK_BUF_SIZE); if(addr_bind(udp_fd,server_addr)<0) return -1; socket_set_nonblocking(udp_fd); struct event *udp_ev = event_new(server->event_base,udp_fd,EV_READ|EV_PERSIST, udp_server_input_handler,server_addr); event_add(udp_ev,NULL); FUNCEND; return 0; }
static int mongo_set_realm_option_one(u08bits *realm, unsigned long value, const char* opt) { mongoc_collection_t * collection = mongo_get_collection("realm"); if(!collection) return -1; bson_t query, doc, child; bson_init(&query); BSON_APPEND_UTF8(&query, "realm", (const char *)realm); bson_init(&doc); size_t klen = 9 + strlen(opt); char * _k = (char *)turn_malloc(klen); strcpy(_k, "options."); strcat(_k, opt); if (value > 0) { bson_append_document_begin(&doc, "$set", -1, &child); BSON_APPEND_INT32(&child, _k, (int32_t)value); bson_append_document_end(&doc, &child); } else { bson_append_document_begin(&doc, "$unset", -1, &child); BSON_APPEND_INT32(&child, _k, 1); bson_append_document_end(&doc, &child); } turn_free(_k,klen); int ret = -1; if (!mongoc_collection_update(collection, MONGOC_UPDATE_MULTI_UPDATE, &query, &doc, NULL, NULL)) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Error deleting origin information\n"); } else { ret = 0; } mongoc_collection_destroy(collection); bson_destroy(&query); bson_destroy(&doc); return ret; }
dtls_listener_relay_server_type* create_dtls_listener_server(const char* ifname, const char *local_address, int port, int verbose, ioa_engine_handle e, turn_turnserver *ts) { dtls_listener_relay_server_type* server=(dtls_listener_relay_server_type*) turn_malloc(sizeof(dtls_listener_relay_server_type)); ns_bzero(server,sizeof(dtls_listener_relay_server_type)); if(init_server(server, ifname, local_address, port, verbose, e, ts)<0) { turn_free(server,sizeof(dtls_listener_relay_server_type)); return NULL; } else { return server; } }
realm_params_t* get_realm(char* name) { if(name && name[0]) { lock_realms(); ur_string_map_value_type value = 0; ur_string_map_key_type key = (ur_string_map_key_type)name; if (ur_string_map_get(realms, key, &value)) { unlock_realms(); return (realm_params_t*)value; } else { realm_params_t *ret = (realm_params_t*)turn_malloc(sizeof(realm_params_t)); ns_bcopy(default_realm_params_ptr,ret,sizeof(realm_params_t)); STRCPY(ret->options.name,name); value = (ur_string_map_value_type)ret; ur_string_map_put(realms, key, value); ret->status.alloc_counters = ur_string_map_create(NULL); add_to_secrets_list(&realms_list, name); unlock_realms(); return ret; } } return default_realm_params_ptr; }
static int create_new_connected_udp_socket( dtls_listener_relay_server_type* server, ioa_socket_handle s) { evutil_socket_t udp_fd = socket(s->local_addr.ss.sa_family, CLIENT_DGRAM_SOCKET_TYPE, CLIENT_DGRAM_SOCKET_PROTOCOL); if (udp_fd < 0) { perror("socket"); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot allocate new socket\n", __FUNCTION__); return -1; } if (sock_bind_to_device(udp_fd, (unsigned char*) (s->e->relay_ifname)) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot bind udp server socket to device %s\n", (char*) (s->e->relay_ifname)); } ioa_socket_handle ret = (ioa_socket*) turn_malloc(sizeof(ioa_socket)); if (!ret) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "%s: Cannot allocate new socket structure\n", __FUNCTION__); close(udp_fd); return -1; } ns_bzero(ret, sizeof(ioa_socket)); ret->magic = SOCKET_MAGIC; ret->fd = udp_fd; ret->family = s->family; ret->st = s->st; ret->sat = CLIENT_SOCKET; ret->local_addr_known = 1; addr_cpy(&(ret->local_addr), &(s->local_addr)); if (addr_bind(udp_fd,&(s->local_addr),1,1,UDP_SOCKET) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot bind new detached udp server socket to local addr\n"); IOA_CLOSE_SOCKET(ret); return -1; } ret->bound = 1; { int connect_err = 0; if (addr_connect(udp_fd, &(server->sm.m.sm.nd.src_addr), &connect_err) < 0) { char sl[129]; char sr[129]; addr_to_string(&(ret->local_addr),(u08bits*)sl); addr_to_string(&(server->sm.m.sm.nd.src_addr),(u08bits*)sr); TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR, "Cannot connect new detached udp client socket from local addr %s to remote addr %s\n",sl,sr); IOA_CLOSE_SOCKET(ret); return -1; } } ret->connected = 1; addr_cpy(&(ret->remote_addr), &(server->sm.m.sm.nd.src_addr)); set_socket_options(ret); ret->current_ttl = s->current_ttl; ret->default_ttl = s->default_ttl; ret->current_tos = s->current_tos; ret->default_tos = s->default_tos; #if DTLS_SUPPORTED if (!turn_params.no_dtls && is_dtls_handshake_message( ioa_network_buffer_data(server->sm.m.sm.nd.nbh), (int) ioa_network_buffer_get_size( server->sm.m.sm.nd.nbh))) { SSL* connecting_ssl = NULL; BIO *wbio = NULL; struct timeval timeout; /* Create BIO */ wbio = BIO_new_dgram(ret->fd, BIO_NOCLOSE); (void) BIO_dgram_set_peer(wbio, (struct sockaddr*) &(server->sm.m.sm.nd.src_addr)); BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_CONNECTED, 0, &(server->sm.m.sm.nd.src_addr)); /* Set and activate timeouts */ timeout.tv_sec = DTLS_MAX_RECV_TIMEOUT; timeout.tv_usec = 0; BIO_ctrl(wbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout); #if DTLSv1_2_SUPPORTED if(get_dtls_version(ioa_network_buffer_data(server->sm.m.sm.nd.nbh), (int)ioa_network_buffer_get_size(server->sm.m.sm.nd.nbh)) == 1) { connecting_ssl = SSL_NEW(server->dtls_ctx_v1_2); } else { connecting_ssl = SSL_NEW(server->dtls_ctx); } #else { connecting_ssl = SSL_NEW(server->dtls_ctx); } #endif SSL_set_accept_state(connecting_ssl); SSL_set_bio(connecting_ssl, NULL, wbio); SSL_set_options(connecting_ssl, SSL_OP_COOKIE_EXCHANGE); SSL_set_max_cert_list(connecting_ssl, 655350); int rc = ssl_read(ret->fd, connecting_ssl, server->sm.m.sm.nd.nbh, server->verbose); if (rc < 0) { if (!(SSL_get_shutdown(connecting_ssl) & SSL_SENT_SHUTDOWN)) { SSL_set_shutdown(connecting_ssl, SSL_RECEIVED_SHUTDOWN); SSL_shutdown(connecting_ssl); } SSL_FREE(connecting_ssl); IOA_CLOSE_SOCKET(ret); return -1; } addr_debug_print(server->verbose, &(server->sm.m.sm.nd.src_addr), "Accepted DTLS connection from"); ret->ssl = connecting_ssl; ioa_network_buffer_delete(server->e, server->sm.m.sm.nd.nbh); server->sm.m.sm.nd.nbh = NULL; ret->st = DTLS_SOCKET; } #endif server->sm.m.sm.s = ret; return server->connect_cb(server->e, &(server->sm)); }
redis_context_handle redisLibeventAttach(struct event_base *base, char *ip0, int port0, char *pwd, int db) { struct redisLibeventEvents *e = NULL; redisAsyncContext *ac = NULL; char ip[256]; if(ip0 && ip0[0]) STRCPY(ip,ip0); else STRCPY(ip,"127.0.0.1"); int port = DEFAULT_REDIS_PORT; if(port0>0) port=port0; ac = redisAsyncConnect(ip, port); if (ac->err) { fprintf(stderr,"Error: %s\n", ac->errstr); return NULL; } /* Create container for context and r/w events */ e = (struct redisLibeventEvents*)turn_malloc(sizeof(struct redisLibeventEvents)); ns_bzero(e,sizeof(struct redisLibeventEvents)); e->allocated = 1; e->context = ac; e->base = base; /* Register functions to start/stop listening for events */ ac->ev.addRead = redisLibeventAddRead; ac->ev.delRead = redisLibeventDelRead; ac->ev.addWrite = redisLibeventAddWrite; ac->ev.delWrite = redisLibeventDelWrite; ac->ev.cleanup = redisLibeventCleanup; ac->ev.data = e; /* Initialize and install read/write events */ e->rev = event_new(e->base,e->context->c.fd, EV_READ|EV_PERSIST,redisLibeventReadEvent, e); e->wev = event_new(e->base,e->context->c.fd, EV_WRITE,redisLibeventWriteEvent, e); if (e->rev == NULL || e->wev == NULL) { turn_free(e, sizeof(struct redisLibeventEvents)); return NULL; } event_add(e->wev, NULL); e->wev_set = 1; struct bufferevent *pair[2]; bufferevent_pair_new(base, TURN_BUFFEREVENTS_OPTIONS, pair); e->in_buf = pair[0]; e->out_buf = pair[1]; bufferevent_setcb(e->in_buf, receive_message_for_redis, NULL, NULL, e); bufferevent_enable(e->in_buf, EV_READ); //Authentication if(pwd) redisAsyncCommand(ac, NULL, e, "AUTH %s", pwd); if(db>0) redisAsyncCommand(ac, NULL, e, "SELECT %d", db); return ac; }
void tcp_data_connect(app_ur_session *elem, u32bits cid) { int clnet_fd; int connect_cycle = 0; again: clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, CLIENT_STREAM_SOCKET_TYPE, CLIENT_STREAM_SOCKET_PROTOCOL); if (clnet_fd < 0) { perror("socket"); exit(-1); } if (sock_bind_to_device(clnet_fd, client_ifname) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind client socket to device %s\n", client_ifname); } set_sock_buf_size(clnet_fd, (UR_CLIENT_SOCK_BUF_SIZE<<2)); ++elem->pinfo.tcp_conn_number; int i = (int)(elem->pinfo.tcp_conn_number-1); elem->pinfo.tcp_conn=(app_tcp_conn_info**)turn_realloc(elem->pinfo.tcp_conn,0,elem->pinfo.tcp_conn_number*sizeof(app_tcp_conn_info*)); elem->pinfo.tcp_conn[i]=(app_tcp_conn_info*)turn_malloc(sizeof(app_tcp_conn_info)); ns_bzero(elem->pinfo.tcp_conn[i],sizeof(app_tcp_conn_info)); elem->pinfo.tcp_conn[i]->tcp_data_fd = clnet_fd; elem->pinfo.tcp_conn[i]->cid = cid; addr_cpy(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),&(elem->pinfo.local_addr)); addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr), 1, 1, TCP_SOCKET); addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); { int cycle = 0; while(cycle++<1024) { int err = 0; if (addr_connect(clnet_fd, &(elem->pinfo.remote_addr),&err) < 0) { if(err == EADDRINUSE) { socket_closesocket(clnet_fd); clnet_fd = socket(elem->pinfo.remote_addr.ss.sa_family, CLIENT_STREAM_SOCKET_TYPE, CLIENT_STREAM_SOCKET_PROTOCOL); if (clnet_fd < 0) { perror("socket"); exit(-1); } if (sock_bind_to_device(clnet_fd, client_ifname) < 0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "Cannot bind client socket to device %s\n", client_ifname); } set_sock_buf_size(clnet_fd, UR_CLIENT_SOCK_BUF_SIZE<<2); elem->pinfo.tcp_conn[i]->tcp_data_fd = clnet_fd; addr_cpy(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),&(elem->pinfo.local_addr)); addr_set_port(&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),0); addr_bind(clnet_fd, &(elem->pinfo.tcp_conn[i]->tcp_data_local_addr),1,1,TCP_SOCKET); addr_get_from_sock(clnet_fd,&(elem->pinfo.tcp_conn[i]->tcp_data_local_addr)); continue; } else { perror("connect"); TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot connect to remote addr\n", __FUNCTION__); exit(-1); } } else { break; } } } if(use_secure) { int try_again = 0; elem->pinfo.tcp_conn[i]->tcp_data_ssl = tls_connect(elem->pinfo.tcp_conn[i]->tcp_data_fd, &(elem->pinfo.remote_addr),&try_again, connect_cycle++); if(!(elem->pinfo.tcp_conn[i]->tcp_data_ssl)) { if(try_again) { --elem->pinfo.tcp_conn_number; goto again; } TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot SSL connect to remote addr\n", __FUNCTION__); exit(-1); } } if(turn_tcp_connection_bind(clnet_verbose, &(elem->pinfo), elem->pinfo.tcp_conn[i],0)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_INFO, "%s: cannot BIND to tcp connection\n", __FUNCTION__); } else { socket_set_nonblocking(clnet_fd); struct event* ev = event_new(client_event_base,clnet_fd, EV_READ|EV_PERSIST,client_input_handler, elem); event_add(ev,NULL); elem->input_tcp_data_ev = ev; addr_debug_print(clnet_verbose, &(elem->pinfo.remote_addr), "TCP data network connected to"); } }