diff --git a/src/apps/relay/http_server.c b/src/apps/relay/http_server.c index d731abc..2d47d32 100644 --- a/src/apps/relay/http_server.c +++ b/src/apps/relay/http_server.c @@ -312,6 +312,13 @@ void str_buffer_append_sz(struct str_buffer* sb, size_t sz) str_buffer_append(sb,ssz); } +void str_buffer_append_sid(struct str_buffer* sb, turnsession_id sid) +{ + char ssz[129]; + snprintf(ssz,sizeof(ssz)-1,"%018llu",(unsigned long long)sid); + str_buffer_append(sb,ssz); +} + const char* str_buffer_get_str(const struct str_buffer *sb) { if(sb) { diff --git a/src/apps/relay/http_server.h b/src/apps/relay/http_server.h index ef40032..8bb3f26 100644 --- a/src/apps/relay/http_server.h +++ b/src/apps/relay/http_server.h @@ -73,6 +73,7 @@ struct str_buffer; struct str_buffer* str_buffer_new(void); void str_buffer_append(struct str_buffer* sb, const char* str); void str_buffer_append_sz(struct str_buffer* sb, size_t sz); +void str_buffer_append_sid(struct str_buffer* sb, turnsession_id sid); const char* str_buffer_get_str(const struct str_buffer *sb); size_t str_buffer_get_str_len(const struct str_buffer *sb); void str_buffer_free(struct str_buffer *sb); diff --git a/src/apps/relay/turn_admin_server.c b/src/apps/relay/turn_admin_server.c index 7b8122d..f2150f1 100644 --- a/src/apps/relay/turn_admin_server.c +++ b/src/apps/relay/turn_admin_server.c @@ -1358,6 +1358,7 @@ enum _AS_FORM { AS_FORM_HOME, AS_FORM_TOGGLE, AS_FORM_UPDATE, + AS_FORM_PS, AS_FORM_UNKNOWN }; @@ -1379,6 +1380,7 @@ static struct form_name form_names[] = { {AS_FORM_HOME,"/home"}, {AS_FORM_TOGGLE,"/toggle"}, {AS_FORM_UPDATE,"/update"}, + {AS_FORM_PS,"/ps"}, {AS_FORM_UNKNOWN,NULL} }; @@ -1460,22 +1462,31 @@ static void write_https_home_page(ioa_socket_handle s) str_buffer_append(sb,"

\r\n"); str_buffer_append(sb,logout_link); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"
Actions:\r\n"); + + str_buffer_append(sb," Realm name: as_eff_realm); + str_buffer_append(sb,"\""); if(!is_superuser()) { - str_buffer_append(sb,"Config Parameters
\r\n"); - } else { - str_buffer_append(sb,"\r\n"); - str_buffer_append(sb,"
Current realm: name:
as_eff_realm); - str_buffer_append(sb,"\">
"); - str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"\r\n"); + str_buffer_append(sb," disabled "); } + str_buffer_append(sb,">
"); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
"); + + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n"); str_buffer_append(sb,"\r\n \r\n\r\n"); @@ -1655,7 +1666,7 @@ static void write_pc_page(ioa_socket_handle s) str_buffer_append(sb,"
\r\n"); str_buffer_append(sb,home_link); str_buffer_append(sb,"
\r\n"); - str_buffer_append(sb,"Config Parameters:
\r\n"); + str_buffer_append(sb,"Configuration Parameters:
\r\n"); str_buffer_append(sb,""); + } + } + + csarg->counter += 1; + } + return 0; +} + +static void https_print_sessions(struct str_buffer* sb) +{ + struct https_ps_arg arg = {sb,0,0}; + + arg.ct = turn_time(); + + ur_map_foreach_arg(cliserver.sessions, (foreachcb_arg_type)https_print_session, &arg); +} + +static void write_ps_page(ioa_socket_handle s) +{ + if(s && !ioa_socket_tobeclosed(s)) { + + if(!(s->as_ok)) { + write_https_logon_page(s); + } else { + + struct str_buffer* sb = str_buffer_new(); + + str_buffer_append(sb,"\r\n\r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"\r\n \r\n \r\n "); + str_buffer_append(sb,admin_title); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,home_link); + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"TURN Sessions:
ParameterCurrent Value"); if(is_superuser()) { str_buffer_append(sb,"New (ephemeral) Value"); @@ -1884,6 +1895,165 @@ static void write_pc_page(ioa_socket_handle s) } } +struct https_ps_arg { + struct str_buffer* sb; + size_t counter; + turn_time_t ct; +}; + +static int https_print_session(ur_map_key_type key, ur_map_value_type value, void *arg) +{ + if(key && value && arg) { + struct https_ps_arg *csarg = (struct https_ps_arg*)arg; + struct str_buffer* sb = csarg->sb; + struct turn_session_info *tsi = (struct turn_session_info *)value; + + if(current_socket->as_eff_realm[0] && strcmp(current_socket->as_eff_realm,tsi->realm)) + return 0; + + if((unsigned long)csarg->counter<(unsigned long)cli_max_output_sessions) { + str_buffer_append(sb,"
"); + str_buffer_append_sz(sb,(size_t)(csarg->counter+1)); + str_buffer_append(sb,""); + str_buffer_append_sid(sb,tsi->id); + str_buffer_append(sb,""); + str_buffer_append(sb,(char*)tsi->username); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->realm); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->origin); + str_buffer_append(sb,""); + if(turn_time_before(csarg->ct, tsi->start_time)) { + str_buffer_append(sb,"undefined time\n"); + } else { + str_buffer_append_sz(sb,(size_t)(csarg->ct - tsi->start_time)); + } + str_buffer_append(sb,""); + if(turn_time_before(tsi->expiration_time,csarg->ct)) { + str_buffer_append(sb,"expired"); + } else { + str_buffer_append_sz(sb,(size_t)(tsi->expiration_time - csarg->ct)); + } + str_buffer_append(sb,""); + str_buffer_append(sb,pname(tsi->client_protocol)); + str_buffer_append(sb,""); + str_buffer_append(sb,pname(tsi->peer_protocol)); + str_buffer_append(sb,""); + { + if(!tsi->local_addr_data.saddr[0]) + addr_to_string(&(tsi->local_addr_data.addr),(u08bits*)tsi->local_addr_data.saddr); + if(!tsi->remote_addr_data.saddr[0]) + addr_to_string(&(tsi->remote_addr_data.addr),(u08bits*)tsi->remote_addr_data.saddr); + if(!tsi->relay_addr_data_ipv4.saddr[0]) + addr_to_string(&(tsi->relay_addr_data_ipv4.addr),(u08bits*)tsi->relay_addr_data_ipv4.saddr); + if(!tsi->relay_addr_data_ipv6.saddr[0]) + addr_to_string(&(tsi->relay_addr_data_ipv6.addr),(u08bits*)tsi->relay_addr_data_ipv6.saddr); + str_buffer_append(sb,tsi->remote_addr_data.saddr); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->local_addr_data.saddr); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->relay_addr_data_ipv4.saddr); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->relay_addr_data_ipv6.saddr); + str_buffer_append(sb,""); + str_buffer_append(sb,get_flag(tsi->enforce_fingerprints)); + str_buffer_append(sb,""); + str_buffer_append(sb,get_flag(tsi->is_mobile)); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->tls_method); + str_buffer_append(sb,""); + str_buffer_append(sb,tsi->tls_cipher); + str_buffer_append(sb,""); + str_buffer_append_sz(sb,(size_t)tsi->bps); + str_buffer_append(sb,""); + { + char str[1025]; + snprintf(str,sizeof(str)-1,"rp=%lu, rb=%lu, sp=%lu, sb=%lu\n",(unsigned long)(tsi->received_packets), (unsigned long)(tsi->received_bytes),(unsigned long)(tsi->sent_packets),(unsigned long)(tsi->sent_bytes)); + str_buffer_append(sb,str); + str_buffer_append(sb,""); + } + { + char str[1025]; + snprintf(str,sizeof(str)-1,"r=%lu, s=%lu, total=%lu (bytes per sec)\n",(unsigned long)(tsi->received_rate), (unsigned long)(tsi->sent_rate),(unsigned long)(tsi->total_rate)); + str_buffer_append(sb,str); + str_buffer_append(sb,""); + } + + if(tsi->main_peers_size) { + size_t i; + for(i=0;imain_peers_size;++i) { + if(!(tsi->main_peers_data[i].saddr[0])) + addr_to_string(&(tsi->main_peers_data[i].addr),(u08bits*)tsi->main_peers_data[i].saddr); + str_buffer_append(sb," "); + str_buffer_append(sb,tsi->main_peers_data[i].saddr); + str_buffer_append(sb," "); + } + if(tsi->extra_peers_size && tsi->extra_peers_data) { + for(i=0;iextra_peers_size;++i) { + if(!(tsi->extra_peers_data[i].saddr[0])) + addr_to_string(&(tsi->extra_peers_data[i].addr),(u08bits*)tsi->extra_peers_data[i].saddr); + str_buffer_append(sb," "); + str_buffer_append(sb,tsi->extra_peers_data[i].saddr); + str_buffer_append(sb," "); + } + } + } + str_buffer_append(sb,"
\r\n"); + str_buffer_append(sb,"\r\n"); + + https_print_sessions(sb); + + str_buffer_append(sb,"\r\n
NSession IDUserRealmOriginAge, secsExpires, secsClient protocolRelay protocolClient addrServer addrRelay addr (IPv4)Relay addr (IPv6)FingerprintsMobileTLS methodTLS cipherBPS (allocated)PacketsRatePeers
\r\n\r\n"); + + send_str_from_ioa_socket_tcp(s,"HTTP/1.1 200 OK\r\nServer: "); + send_str_from_ioa_socket_tcp(s,TURN_SOFTWARE); + send_str_from_ioa_socket_tcp(s,"\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: "); + + send_ulong_from_ioa_socket_tcp(s,str_buffer_get_str_len(sb)); + + send_str_from_ioa_socket_tcp(s,"\r\n\r\n"); + send_str_from_ioa_socket_tcp(s,str_buffer_get_str(sb)); + + str_buffer_free(sb); + } + } +} + static void handle_toggle_request(ioa_socket_handle s, struct http_request* hr) { if(s && hr) { @@ -1977,6 +2147,20 @@ static void handle_https(ioa_socket_handle s, ioa_network_buffer_handle nbh) } break; } + case AS_FORM_PS: { + if(s->as_ok) { + const char *realm0 = get_http_header_value(hr, HR_REALM); + if(!realm0 || !realm0[0]) + realm0=get_realm(NULL)->options.name; + if(!is_superuser()) + realm0 = current_socket->as_realm; + STRCPY(current_socket->as_eff_realm,realm0); + write_ps_page(s); + } else { + write_https_logon_page(s); + } + break; + } case AS_FORM_TOGGLE: if(s->as_ok) { handle_toggle_request(s,hr);