From 0336cfaeb3a6f76804d965110152c967d58ed1bf Mon Sep 17 00:00:00 2001 From: zongor Date: Sun, 10 Sep 2023 20:22:32 -0400 Subject: [PATCH] add server protocol, add test --- fortran/server/README.md | 3 - fortran/server/app/main.f90 | 49 ++++++++---- fortran/server/src/db.f90 | 115 ++++++++++++++++++++++++++-- fortran/server/test.sh | 2 +- fortran/server/test/server_test.f90 | 7 ++ fortran/www/app/main.f90 | 2 +- fortran/www/src/db.f90 | 115 ++++++++++++++++++++++++++-- 7 files changed, 261 insertions(+), 32 deletions(-) create mode 100644 fortran/server/test/server_test.f90 diff --git a/fortran/server/README.md b/fortran/server/README.md index b2e584a..d137d2f 100644 --- a/fortran/server/README.md +++ b/fortran/server/README.md @@ -8,9 +8,6 @@ - logout - move - str(24) :: username - - int :: timestamp - - str(?) :: data - - int :: data_length - double :: x_pos - double :: y_pos diff --git a/fortran/server/app/main.f90 b/fortran/server/app/main.f90 index f23f22b..95cd068 100644 --- a/fortran/server/app/main.f90 +++ b/fortran/server/app/main.f90 @@ -1,14 +1,15 @@ program main - use, intrinsic :: iso_c_binding use iso_fortran_env - use :: sqlite3 + use, intrinsic :: iso_c_binding use db implicit none - - character, dimension(:), allocatable :: form_data + type(db_type) :: db character(len=128):: db_path - integer :: err, i, length + character(len=24):: username + real(kind=c_double) :: x_pos + real(kind=c_double) :: y_pos + integer :: command, rc logical :: exist inquire (file="debug.log", exist=exist) @@ -18,20 +19,38 @@ program main open (12, file="debug.log", status="new", action="write") end if + call getarg(1, db_path) + + inquire (file=db_path(:Len_Trim(db_path)), exist=exist) + if (.not. exist) then + stop 1 + end if + + rc = db_open(db, db_path(:Len_Trim(db_path))) ! do while not logged out + server_loop: do ! read message from stdin + read(input_unit, "(i3, 1x, a24, 1x, f8.2, 1x, f8.2)") command, username, x_pos, y_pos - ! if ping then get all logged in users and return their positions to client + if (command .eq. 0) then ! get all logged in users and return their positions to client + rc = db_count_logged_in_users(db) + rc = db_get_logged_in_users(db) + else if (command .eq. 1) then + rc = db_login_user(db, username) + rc = db_count_logged_in_users(db) + rc = db_get_logged_in_users(db) + else if (command .eq. 3) then ! update new pos to database + rc = db_move_user(db, username, x_pos, y_pos) + rc = db_count_logged_in_users(db) + rc = db_get_logged_in_users(db) + else ! (2) if logout update logged_in to database + rc = db_logout_user(db, username) + exit server_loop + end if + end do server_loop - ! if move update new pos to database - - ! if logout update logged_in to database - - ! end do - - ! send logout all to clients - -contains + rc = db_close(db) + close(12) end program main diff --git a/fortran/server/src/db.f90 b/fortran/server/src/db.f90 index 5cac73e..dbea6e8 100644 --- a/fortran/server/src/db.f90 +++ b/fortran/server/src/db.f90 @@ -1,6 +1,6 @@ ! db.f90 module db - !! Database abstraction layer. + use iso_fortran_env use, intrinsic :: iso_c_binding use :: sqlite3 implicit none @@ -16,7 +16,11 @@ module db public :: db_open public :: db_create_users public :: db_get_logged_in_users + public :: db_count_logged_in_users public :: db_add_user + public :: db_login_user + public :: db_logout_user + public :: db_move_user public :: db_delete_user private :: db_error @@ -137,16 +141,48 @@ contains call db_error(rc, 'sqlite3_finalize()') end function db_delete_user + integer function db_count_logged_in_users(db) result(rc) + !! Prints number of courses per student to standard output. + type(db_type), intent(inout) :: db + + type(c_ptr) :: stmt + integer :: count + + rc = sqlite3_prepare_v2(db%ptr, "SELECT count(logged_in) FROM users u WHERE u.logged_in = 1;", stmt) + call db_error(rc, 'sqlite3_prepare_v2()') + + step_loop: do + rc = sqlite3_step(stmt) + + select case (rc) + case (SQLITE_ROW) + count = sqlite3_column_int(stmt, 0) + write(output_unit, "(i0)") count + + case (SQLITE_DONE) + exit step_loop + + case default + call db_error(rc, 'sqlite3_step()') + exit step_loop + end select + end do step_loop + + rc = sqlite3_finalize(stmt) + call db_error(rc, 'sqlite3_finalize()') + end function db_count_logged_in_users + integer function db_get_logged_in_users(db) result(rc) !! Prints number of courses per student to standard output. type(db_type), intent(inout) :: db type(c_ptr) :: stmt character(len=24) :: username - real(kind=c_double) :: x_pos, y_pos + integer :: apperance_r, apperance_g, apperance_b + real :: x_pos, y_pos rc = sqlite3_prepare_v2(db%ptr, & - "SELECT username, x_pos, y_pos " // & + "SELECT username, apperance_r, apperance_g, apperance_b, x_pos, y_pos " // & "FROM users u WHERE u.logged_in = 1;", stmt) call db_error(rc, 'sqlite3_prepare_v2()') @@ -156,9 +192,13 @@ contains select case (rc) case (SQLITE_ROW) username = sqlite3_column_text(stmt, 0) - x_pos = sqlite3_column_double(stmt, 1) - y_pos = sqlite3_column_double(stmt, 1) - write(12, *) username, x_pos, y_pos + apperance_r = sqlite3_column_int(stmt, 1) + apperance_g = sqlite3_column_int(stmt, 2) + apperance_b = sqlite3_column_int(stmt, 3) + x_pos = sqlite3_column_double(stmt, 4) + y_pos = sqlite3_column_double(stmt, 5) + write(output_unit, "(a24, 1x, i3, 1x, i3, 1x, i3, 1x, f8.2, 1x, f8.2)") username(:Len_Trim(username)), & + apperance_r, apperance_g, apperance_b, x_pos, y_pos case (SQLITE_DONE) exit step_loop @@ -173,6 +213,69 @@ contains call db_error(rc, 'sqlite3_finalize()') end function db_get_logged_in_users + integer function db_login_user(db, username) result(rc) + type(db_type), intent(inout) :: db + character(len=24), intent(in) :: username + type(c_ptr) :: stmt + + rc = sqlite3_prepare_v2(db%ptr, & + "UPDATE users SET logged_in = 1 WHERE users.username = ?;", stmt) + call db_error(rc, 'sqlite3_prepare_v2()') + + rc = sqlite3_bind_text(stmt, 1, username) + call db_error(rc, 'sqlite3_bind_text()') + + rc = sqlite3_step(stmt) + call db_error(rc, 'sqlite3_step()') + + rc = sqlite3_finalize(stmt) + call db_error(rc, 'sqlite3_finalize()') + end function db_login_user + + integer function db_logout_user(db, username) result(rc) + type(db_type), intent(inout) :: db + character(len=24), intent(in) :: username + type(c_ptr) :: stmt + + rc = sqlite3_prepare_v2(db%ptr, & + "UPDATE users SET logged_in = 0 WHERE users.username = ?;", stmt) + call db_error(rc, 'sqlite3_prepare_v2()') + + rc = sqlite3_bind_text(stmt, 1, username) + call db_error(rc, 'sqlite3_bind_text()') + + rc = sqlite3_step(stmt) + call db_error(rc, 'sqlite3_step()') + + rc = sqlite3_finalize(stmt) + call db_error(rc, 'sqlite3_finalize()') + end function db_logout_user + + integer function db_move_user(db, username, x_pos, y_pos) result(rc) + type(db_type), intent(inout) :: db + character(len=24), intent(in) :: username + real(kind=c_double), intent(in) :: x_pos + real(kind=c_double), intent(in) :: y_pos + type(c_ptr) :: stmt + + rc = sqlite3_prepare_v2(db%ptr, & + "UPDATE users SET x_pos = ?, y_pos = ? WHERE users.username = ?;", stmt) + call db_error(rc, 'sqlite3_prepare_v2()') + + rc = sqlite3_bind_double(stmt, 1, x_pos) + call db_error(rc, 'sqlite3_bind_double()') + rc = sqlite3_bind_double(stmt, 2, y_pos) + call db_error(rc, 'sqlite3_bind_double()') + rc = sqlite3_bind_text(stmt, 3, username) + call db_error(rc, 'sqlite3_bind_text()') + + rc = sqlite3_step(stmt) + call db_error(rc, 'sqlite3_step()') + + rc = sqlite3_finalize(stmt) + call db_error(rc, 'sqlite3_finalize()') + end function db_move_user + subroutine db_error(code, proc, err_msg) !! Prints error message. integer, intent(in) :: code diff --git a/fortran/server/test.sh b/fortran/server/test.sh index 2cfcf9f..456f531 100755 --- a/fortran/server/test.sh +++ b/fortran/server/test.sh @@ -1,2 +1,2 @@ #!/bin/sh -listen1 'tcp!*!1234' ~/.local/bin/fortran-micro-httpd ../../common/html/index.html ../../common/sql/test.db3 +listen1 'tcp!*!35565' ~/.local/bin/fortran-mmo-server ../../common/sql/test.db3 diff --git a/fortran/server/test/server_test.f90 b/fortran/server/test/server_test.f90 new file mode 100644 index 0000000..68dc289 --- /dev/null +++ b/fortran/server/test/server_test.f90 @@ -0,0 +1,7 @@ +program main + use iso_fortran_env + implicit none + + write(output_unit, "(i3, 1x, a24, 1x, f8.2, 1x, f8.2)") 0, 'chakr', 0.0, 0.0 + +end program main \ No newline at end of file diff --git a/fortran/www/app/main.f90 b/fortran/www/app/main.f90 index e86dfb0..70b697e 100644 --- a/fortran/www/app/main.f90 +++ b/fortran/www/app/main.f90 @@ -142,5 +142,5 @@ contains val = shiftl(a, 4) + b end function hex2int - + end program main diff --git a/fortran/www/src/db.f90 b/fortran/www/src/db.f90 index 5cac73e..1034adc 100644 --- a/fortran/www/src/db.f90 +++ b/fortran/www/src/db.f90 @@ -1,6 +1,6 @@ ! db.f90 module db - !! Database abstraction layer. + use iso_fortran_env use, intrinsic :: iso_c_binding use :: sqlite3 implicit none @@ -16,7 +16,11 @@ module db public :: db_open public :: db_create_users public :: db_get_logged_in_users + public :: db_count_logged_in_users public :: db_add_user + public :: db_login_user + public :: db_logout_user + public :: db_move_user public :: db_delete_user private :: db_error @@ -137,16 +141,48 @@ contains call db_error(rc, 'sqlite3_finalize()') end function db_delete_user + integer function db_count_logged_in_users(db) result(rc) + !! Prints number of courses per student to standard output. + type(db_type), intent(inout) :: db + + type(c_ptr) :: stmt + integer :: count + + rc = sqlite3_prepare_v2(db%ptr, "SELECT count(logged_in) FROM users u WHERE u.logged_in = 1;", stmt) + call db_error(rc, 'sqlite3_prepare_v2()') + + step_loop: do + rc = sqlite3_step(stmt) + + select case (rc) + case (SQLITE_ROW) + count = sqlite3_column_int(stmt, 0) + write(output_unit, "(i0)") count + + case (SQLITE_DONE) + exit step_loop + + case default + call db_error(rc, 'sqlite3_step()') + exit step_loop + end select + end do step_loop + + rc = sqlite3_finalize(stmt) + call db_error(rc, 'sqlite3_finalize()') + end function db_count_logged_in_users + integer function db_get_logged_in_users(db) result(rc) !! Prints number of courses per student to standard output. type(db_type), intent(inout) :: db type(c_ptr) :: stmt character(len=24) :: username - real(kind=c_double) :: x_pos, y_pos + integer :: apperance_r, apperance_g, apperance_b + real :: x_pos, y_pos rc = sqlite3_prepare_v2(db%ptr, & - "SELECT username, x_pos, y_pos " // & + "SELECT username, apperance_r, apperance_g, apperance_b, x_pos, y_pos " // & "FROM users u WHERE u.logged_in = 1;", stmt) call db_error(rc, 'sqlite3_prepare_v2()') @@ -156,9 +192,13 @@ contains select case (rc) case (SQLITE_ROW) username = sqlite3_column_text(stmt, 0) - x_pos = sqlite3_column_double(stmt, 1) - y_pos = sqlite3_column_double(stmt, 1) - write(12, *) username, x_pos, y_pos + apperance_r = sqlite3_column_int(stmt, 1) + apperance_g = sqlite3_column_int(stmt, 2) + apperance_b = sqlite3_column_int(stmt, 3) + x_pos = sqlite3_column_double(stmt, 4) + y_pos = sqlite3_column_double(stmt, 5) + write(output_unit, "(a24, i3, i3, i3, f8.2, f8.2)") username(:Len_Trim(username)), & + apperance_r, apperance_g, apperance_b, x_pos, y_pos case (SQLITE_DONE) exit step_loop @@ -173,6 +213,69 @@ contains call db_error(rc, 'sqlite3_finalize()') end function db_get_logged_in_users + integer function db_login_user(db, username) result(rc) + type(db_type), intent(inout) :: db + character(len=24), intent(in) :: username + type(c_ptr) :: stmt + + rc = sqlite3_prepare_v2(db%ptr, & + "UPDATE users SET logged_in = 1 WHERE users.username = ?;", stmt) + call db_error(rc, 'sqlite3_prepare_v2()') + + rc = sqlite3_bind_text(stmt, 1, username) + call db_error(rc, 'sqlite3_bind_text()') + + rc = sqlite3_step(stmt) + call db_error(rc, 'sqlite3_step()') + + rc = sqlite3_finalize(stmt) + call db_error(rc, 'sqlite3_finalize()') + end function db_login_user + + integer function db_logout_user(db, username) result(rc) + type(db_type), intent(inout) :: db + character(len=24), intent(in) :: username + type(c_ptr) :: stmt + + rc = sqlite3_prepare_v2(db%ptr, & + "UPDATE users SET logged_in = 0 WHERE users.username = ?;", stmt) + call db_error(rc, 'sqlite3_prepare_v2()') + + rc = sqlite3_bind_text(stmt, 1, username) + call db_error(rc, 'sqlite3_bind_text()') + + rc = sqlite3_step(stmt) + call db_error(rc, 'sqlite3_step()') + + rc = sqlite3_finalize(stmt) + call db_error(rc, 'sqlite3_finalize()') + end function db_logout_user + + integer function db_move_user(db, username, x_pos, y_pos) result(rc) + type(db_type), intent(inout) :: db + character(len=24), intent(in) :: username + real(kind=c_double), intent(in) :: x_pos + real(kind=c_double), intent(in) :: y_pos + type(c_ptr) :: stmt + + rc = sqlite3_prepare_v2(db%ptr, & + "UPDATE users SET x_pos = ?, y_pos = ? WHERE users.username = ?;", stmt) + call db_error(rc, 'sqlite3_prepare_v2()') + + rc = sqlite3_bind_double(stmt, 1, x_pos) + call db_error(rc, 'sqlite3_bind_double()') + rc = sqlite3_bind_double(stmt, 2, y_pos) + call db_error(rc, 'sqlite3_bind_double()') + rc = sqlite3_bind_text(stmt, 3, username) + call db_error(rc, 'sqlite3_bind_text()') + + rc = sqlite3_step(stmt) + call db_error(rc, 'sqlite3_step()') + + rc = sqlite3_finalize(stmt) + call db_error(rc, 'sqlite3_finalize()') + end function db_move_user + subroutine db_error(code, proc, err_msg) !! Prints error message. integer, intent(in) :: code