add server protocol, add test

This commit is contained in:
zongor 2023-09-10 20:22:32 -04:00
parent 79859bbec7
commit 0336cfaeb3
7 changed files with 261 additions and 32 deletions

View File

@ -8,9 +8,6 @@
- logout - logout
- move - move
- str(24) :: username - str(24) :: username
- int :: timestamp
- str(?) :: data
- int :: data_length
- double :: x_pos - double :: x_pos
- double :: y_pos - double :: y_pos

View File

@ -1,14 +1,15 @@
program main program main
use, intrinsic :: iso_c_binding
use iso_fortran_env use iso_fortran_env
use :: sqlite3 use, intrinsic :: iso_c_binding
use db use db
implicit none implicit none
type(db_type) :: db
character, dimension(:), allocatable :: form_data
character(len=128):: db_path 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 logical :: exist
inquire (file="debug.log", exist=exist) inquire (file="debug.log", exist=exist)
@ -18,20 +19,38 @@ program main
open (12, file="debug.log", status="new", action="write") open (12, file="debug.log", status="new", action="write")
end if 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 ! do while not logged out
server_loop: do
! read message from stdin ! 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 rc = db_close(db)
close(12)
! if logout update logged_in to database
! end do
! send logout all to clients
contains
end program main end program main

View File

@ -1,6 +1,6 @@
! db.f90 ! db.f90
module db module db
!! Database abstraction layer. use iso_fortran_env
use, intrinsic :: iso_c_binding use, intrinsic :: iso_c_binding
use :: sqlite3 use :: sqlite3
implicit none implicit none
@ -16,7 +16,11 @@ module db
public :: db_open public :: db_open
public :: db_create_users public :: db_create_users
public :: db_get_logged_in_users public :: db_get_logged_in_users
public :: db_count_logged_in_users
public :: db_add_user public :: db_add_user
public :: db_login_user
public :: db_logout_user
public :: db_move_user
public :: db_delete_user public :: db_delete_user
private :: db_error private :: db_error
@ -137,16 +141,48 @@ contains
call db_error(rc, 'sqlite3_finalize()') call db_error(rc, 'sqlite3_finalize()')
end function db_delete_user 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) integer function db_get_logged_in_users(db) result(rc)
!! Prints number of courses per student to standard output. !! Prints number of courses per student to standard output.
type(db_type), intent(inout) :: db type(db_type), intent(inout) :: db
type(c_ptr) :: stmt type(c_ptr) :: stmt
character(len=24) :: username 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, & 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) "FROM users u WHERE u.logged_in = 1;", stmt)
call db_error(rc, 'sqlite3_prepare_v2()') call db_error(rc, 'sqlite3_prepare_v2()')
@ -156,9 +192,13 @@ contains
select case (rc) select case (rc)
case (SQLITE_ROW) case (SQLITE_ROW)
username = sqlite3_column_text(stmt, 0) username = sqlite3_column_text(stmt, 0)
x_pos = sqlite3_column_double(stmt, 1) apperance_r = sqlite3_column_int(stmt, 1)
y_pos = sqlite3_column_double(stmt, 1) apperance_g = sqlite3_column_int(stmt, 2)
write(12, *) username, x_pos, y_pos 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) case (SQLITE_DONE)
exit step_loop exit step_loop
@ -173,6 +213,69 @@ contains
call db_error(rc, 'sqlite3_finalize()') call db_error(rc, 'sqlite3_finalize()')
end function db_get_logged_in_users 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) subroutine db_error(code, proc, err_msg)
!! Prints error message. !! Prints error message.
integer, intent(in) :: code integer, intent(in) :: code

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/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

View File

@ -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

View File

@ -1,6 +1,6 @@
! db.f90 ! db.f90
module db module db
!! Database abstraction layer. use iso_fortran_env
use, intrinsic :: iso_c_binding use, intrinsic :: iso_c_binding
use :: sqlite3 use :: sqlite3
implicit none implicit none
@ -16,7 +16,11 @@ module db
public :: db_open public :: db_open
public :: db_create_users public :: db_create_users
public :: db_get_logged_in_users public :: db_get_logged_in_users
public :: db_count_logged_in_users
public :: db_add_user public :: db_add_user
public :: db_login_user
public :: db_logout_user
public :: db_move_user
public :: db_delete_user public :: db_delete_user
private :: db_error private :: db_error
@ -137,16 +141,48 @@ contains
call db_error(rc, 'sqlite3_finalize()') call db_error(rc, 'sqlite3_finalize()')
end function db_delete_user 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) integer function db_get_logged_in_users(db) result(rc)
!! Prints number of courses per student to standard output. !! Prints number of courses per student to standard output.
type(db_type), intent(inout) :: db type(db_type), intent(inout) :: db
type(c_ptr) :: stmt type(c_ptr) :: stmt
character(len=24) :: username 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, & 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) "FROM users u WHERE u.logged_in = 1;", stmt)
call db_error(rc, 'sqlite3_prepare_v2()') call db_error(rc, 'sqlite3_prepare_v2()')
@ -156,9 +192,13 @@ contains
select case (rc) select case (rc)
case (SQLITE_ROW) case (SQLITE_ROW)
username = sqlite3_column_text(stmt, 0) username = sqlite3_column_text(stmt, 0)
x_pos = sqlite3_column_double(stmt, 1) apperance_r = sqlite3_column_int(stmt, 1)
y_pos = sqlite3_column_double(stmt, 1) apperance_g = sqlite3_column_int(stmt, 2)
write(12, *) username, x_pos, y_pos 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) case (SQLITE_DONE)
exit step_loop exit step_loop
@ -173,6 +213,69 @@ contains
call db_error(rc, 'sqlite3_finalize()') call db_error(rc, 'sqlite3_finalize()')
end function db_get_logged_in_users 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) subroutine db_error(code, proc, err_msg)
!! Prints error message. !! Prints error message.
integer, intent(in) :: code integer, intent(in) :: code