From 83911cc5f74a0eee2401c03b4afb2ae9aace5c65 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Fri, 14 Apr 2017 17:10:20 -0400 Subject: server now logs all received conversations and events to files --- Hermes/TODO | 2 ++ Hermes/client.rkt | 3 ++- Hermes/server.rkt | 69 ++++++++++++++++++++++++++++++++++++------------------- 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/Hermes/TODO b/Hermes/TODO index 8ad5a92..7b2c43f 100644 --- a/Hermes/TODO +++ b/Hermes/TODO @@ -12,3 +12,5 @@ e 14. bye message prompt for clients 15. Session stickiness for clients 16. plain tcp -> ssl based +17. fix breaks for improper disconnects from clients +18. Add topics after project completion diff --git a/Hermes/client.rkt b/Hermes/client.rkt index 3b65cfa..745cf84 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -6,6 +6,7 @@ ;; notes: output may need to be aligned and formatted nicely (define host "10.0.0.160") ; internal home (define host2 "67.186.191.81") +(define host3 "localhost") (define port-num 4321) @@ -15,7 +16,7 @@ (define (client port-no) (parameterize ([current-custodian main-client-cust]) ;; connect to server at port 8080 - (define-values (in out) (tcp-connect host2 port-no)) ;; define values + (define-values (in out) (tcp-connect host3 port-no)) ;; define values (display in) (displayln out) ;; binds to multiple values akin to unpacking tuples in python diff --git a/Hermes/server.rkt b/Hermes/server.rkt index 5673eca..54b1384 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -3,6 +3,8 @@ ;; globals (define welcome-message "Welcome to Hermes coms. Type your message below") +(define successful-connection-m "Successfully connected to a client. Sending client a welcome message.") + ; track number of connections with closure (define (make-count no-count) (define (increment) @@ -71,16 +73,32 @@ (define messages-s (make-semaphore 1)) ;; control access to messages ;; Several threads may want to print to stdout, so lets make things civil +; constant always available (define stdout (make-semaphore 1)) +; TODO refactor to take a port. defaults to current-output port in this context ; Takes a string and a semaphore to print safely to stdout (define displayln-safe - (lambda (a-string a-semaphore) - (semaphore-wait a-semaphore) - (displayln a-string) - (semaphore-post a-semaphore))) - - + (lambda (a-string [a-semaphore stdout] [a-output-port (current-output-port)]) + (cond [(not (and (eq? a-semaphore stdout) (eq? a-output-port (current-output-port)))) + (semaphore-wait a-semaphore) + (semaphore-wait stdout) + (displayln a-string a-output-port) + (flush-output a-output-port) + (displayln a-string) + (semaphore-post stdout) + (semaphore-post a-semaphore)] + [else + (semaphore-wait stdout) + (displayln a-string) + (semaphore-post stdout)]))) + +; two files to store error messages, and channel conversations +(define error-out (open-output-file "/home/pcuser/Hermes/Hermes/error.txt" #:exists 'append)) +(define convs-out (open-output-file "/home/pcuser/Hermes/Hermes/conversations.txt" #:exists 'append)) +(define error-out-s (make-semaphore 1)) +(define convs-out-s (make-semaphore 1)) +; TODO finish logging all error related messages to (define (serve port-no) (define main-cust (make-custodian)) (parameterize ([current-custodian main-cust]) @@ -88,17 +106,24 @@ (define (loop) (accept-and-handle listener) (loop)) - (displayln "threading the listener") + (displayln-safe "Starting up the listener." error-out-s error-out) (thread loop) + (displayln-safe "Listener successfully started." error-out-s error-out) ;; Create a thread whose job is to simply call broadcast iteratively (thread (lambda () - (displayln-safe "Broadcast thread started!\n" stdout) + (displayln-safe "Broadcast thread started!\n") (let loopb [] (sleep 0.5) ;; wait 0.5 secs before beginning to broadcast (broadcast) (loopb))))) (lambda () - (displayln "\nGoodbye, shutting down all services\n") + (displayln-safe "Goodbye, shutting down all services" error-out-s error-out) + (semaphore-wait error-out-s) + (semaphore-wait convs-out-s) + (close-output-port error-out) + (close-output-port convs-out) + (semaphore-post error-out-s) + (semaphore-post convs-out-s) (custodian-shutdown-all main-cust))) (define (accept-and-handle listener) @@ -110,16 +135,13 @@ ((c-count 'increment)) (semaphore-post c-count-s) - (displayln-safe (string-append - "Successfully connected to a client. " - "Sending client a welcome message.") - stdout) + (displayln-safe successful-connection-m) (displayln welcome-message out) ;; print to server log and client (define print-no-users (string-append "Number of users in chat: " (number->string ((c-count 'current-count))))) (displayln print-no-users out) - (displayln-safe print-no-users stdout) + (displayln-safe print-no-users convs-out-s convs-out) (flush-output out) (semaphore-wait connections-s) ((c-connections 'add) in out) @@ -134,7 +156,7 @@ (thread (lambda () (displayln-safe (string-append "Started a thread to kill hanging " - "connecting threads") stdout) + "connecting threads")) (sleep 1360) (custodian-shutdown-all cust))))) @@ -143,13 +165,11 @@ (define (something-to-say in) (define evt-t0 (sync/timeout 60 (read-line-evt in 'linefeed))) (cond [(eof-object? evt-t0) - ; TODO remove pair of ports associated with client (semaphore-wait connections-s) ((c-connections 'remove-ports) in out) (semaphore-post connections-s) - - (displayln-safe "Connection closed. EOF received" - stdout) + ; TODO some form of identification for this client + (displayln-safe "Connection closed. EOF received" error-out-s error-out) (semaphore-wait c-count-s) ((c-count 'decrement)) (semaphore-post c-count-s) @@ -157,12 +177,12 @@ (kill-thread (current-thread))] [(string? evt-t0) (semaphore-wait messages-s) - ; append the message to list of messages - (display (string-append evt-t0 "\n")) + ; append the message to list of messages NO NEED done during broadcast + ; (displayln-safe evt-t0 convs-out-s convs-out) ((c-messages 'add) evt-t0) (semaphore-post messages-s)] [else - (displayln-safe "Timeout waiting. Nothing received from client" stdout)])) + (displayln-safe "Timeout waiting. Nothing received from client")])) ; Executes methods above in another thread (thread (lambda () @@ -180,6 +200,8 @@ (car ports)) ; broadcasts received message from clients periodically +; TODO before broadcasting the message make sure the ports is still open +; no EOF if it is remove client from connections (define broadcast (lambda () (semaphore-wait messages-s) @@ -189,6 +211,7 @@ (displayln (first ((c-messages 'mes-list))) (get-output-port ports)) (flush-output (get-output-port ports))) ((c-connections 'cons-list))) + (displayln-safe (first ((c-messages 'mes-list))) convs-out-s convs-out) ;; remove top message ((c-messages 'remove-top)) (displayln "Message broadcasted"))]) @@ -196,4 +219,4 @@ ; TODO move to its own file (define stop (serve 4321)) ;; start server then close with stop -(display "Server process started\n") +(displayln-safe "Server process started\n" error-out-s error-out) -- cgit v1.2.3 From 11bcec105200eef5da68bce4f1952338d204d8c1 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sat, 15 Apr 2017 20:32:26 -0400 Subject: preliminary work on adding sessions stickiness --- Hermes/TODO | 5 +++-- Hermes/client.rkt | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Hermes/TODO b/Hermes/TODO index 7b2c43f..f5f0a1c 100644 --- a/Hermes/TODO +++ b/Hermes/TODO @@ -1,6 +1,5 @@ FEATURES 1. Create a racket module for commonly used functions -2. Log error messages and channel conservations to proper files on server 4. message parsable? 5. command parsable? 7. maybe fiddle around with irc library @@ -10,7 +9,9 @@ FEATURES e 12. Hide user's own input in command line 14. bye message prompt for clients -15. Session stickiness for clients +*15. Session stickiness for clients. Log received comms to a local file. +additionally save user details and prompt user to use defaults or create +new ones 16. plain tcp -> ssl based 17. fix breaks for improper disconnects from clients 18. Add topics after project completion diff --git a/Hermes/client.rkt b/Hermes/client.rkt index 745cf84..5e99a96 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -1,14 +1,26 @@ #lang racket (require math/base) ;; for random number generation ;; TODO clean up string message output and alignment +;; i.e. seconds and minutes hours specifically ;; author: Ibrahim Mkusa ;; about: print and read concurrently ;; notes: output may need to be aligned and formatted nicely + + + (define host "10.0.0.160") ; internal home (define host2 "67.186.191.81") (define host3 "localhost") (define port-num 4321) +(define hermes-conf (open-output-file "./hermes.conf" 'append)) +(define hermes-conf-s (make-semaphore 1)) + +(define convs-out (open-output-file "./convs.out" 'append)) +(define convs-out-s (make-semaphore 1)) + +(define error-out (open-output-file "./error.out" 'append)) +(define error-out-s (make-semaphore 1)) ; custodian for client connections (define main-client-cust (make-custodian)) @@ -17,9 +29,10 @@ (parameterize ([current-custodian main-client-cust]) ;; connect to server at port 8080 (define-values (in out) (tcp-connect host3 port-no)) ;; define values - (display in) - (displayln out) ;; binds to multiple values akin to unpacking tuples in python + + ; store username to a file for later retrieval along with relevent + ; info used for authentication with server (displayln "What's your name?") (define username (read-line)) -- cgit v1.2.3 From 413d13d7a65fdb6797903a0c56808730fd265b37 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sat, 15 Apr 2017 20:56:47 -0400 Subject: created modules/general.rkt to house common functions --- .gitignore | 8 ++++++++ Hermes/client.rkt | 6 +++--- Hermes/modules/general.rkt | 24 ++++++++++++++++++++++++ Hermes/server.rkt | 24 +++--------------------- 4 files changed, 38 insertions(+), 24 deletions(-) create mode 100644 Hermes/modules/general.rkt diff --git a/.gitignore b/.gitignore index 49a9d25..7c07843 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,10 @@ # ignore temporary files *~ + +# ignore logs and configuration files +*.out +*.conf + +# ignore racket compile files +*.dep +*.zo diff --git a/Hermes/client.rkt b/Hermes/client.rkt index 5e99a96..9f20dc4 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -13,13 +13,13 @@ (define host3 "localhost") (define port-num 4321) -(define hermes-conf (open-output-file "./hermes.conf" 'append)) +(define hermes-conf (open-output-file "./hermes.conf" #:exists'append)) (define hermes-conf-s (make-semaphore 1)) -(define convs-out (open-output-file "./convs.out" 'append)) +(define convs-out (open-output-file "./convs.out" #:exists 'append)) (define convs-out-s (make-semaphore 1)) -(define error-out (open-output-file "./error.out" 'append)) +(define error-out (open-output-file "./error.out" #:exists 'append)) (define error-out-s (make-semaphore 1)) ; custodian for client connections diff --git a/Hermes/modules/general.rkt b/Hermes/modules/general.rkt new file mode 100644 index 0000000..b33eb8a --- /dev/null +++ b/Hermes/modules/general.rkt @@ -0,0 +1,24 @@ +#lang racket + +(provide displayln-safe) +;; Several threads may want to print to stdout, so lets make things civil +; constant always available +(define stdout (make-semaphore 1)) + +; prints to stdout with an optional output port +; requires a specified semaphore for the optional output port +(define displayln-safe + (lambda (a-string [a-semaphore stdout] [a-output-port (current-output-port)]) + (cond [(not (and (eq? a-semaphore stdout) (eq? a-output-port (current-output-port)))) + (semaphore-wait a-semaphore) + (semaphore-wait stdout) + (displayln a-string a-output-port) + (flush-output a-output-port) + (displayln a-string) + (semaphore-post stdout) + (semaphore-post a-semaphore)] + [else + (semaphore-wait stdout) + (displayln a-string) + (semaphore-post stdout)]))) + diff --git a/Hermes/server.rkt b/Hermes/server.rkt index 54b1384..a309ddc 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -1,6 +1,9 @@ #lang racket + +(require "modules/general.rkt") (require math/base) ;; for random number generation + ;; globals (define welcome-message "Welcome to Hermes coms. Type your message below") (define successful-connection-m "Successfully connected to a client. Sending client a welcome message.") @@ -72,27 +75,6 @@ ; semaphore to control access to c-messages (define messages-s (make-semaphore 1)) ;; control access to messages -;; Several threads may want to print to stdout, so lets make things civil -; constant always available -(define stdout (make-semaphore 1)) - -; TODO refactor to take a port. defaults to current-output port in this context -; Takes a string and a semaphore to print safely to stdout -(define displayln-safe - (lambda (a-string [a-semaphore stdout] [a-output-port (current-output-port)]) - (cond [(not (and (eq? a-semaphore stdout) (eq? a-output-port (current-output-port)))) - (semaphore-wait a-semaphore) - (semaphore-wait stdout) - (displayln a-string a-output-port) - (flush-output a-output-port) - (displayln a-string) - (semaphore-post stdout) - (semaphore-post a-semaphore)] - [else - (semaphore-wait stdout) - (displayln a-string) - (semaphore-post stdout)]))) - ; two files to store error messages, and channel conversations (define error-out (open-output-file "/home/pcuser/Hermes/Hermes/error.txt" #:exists 'append)) (define convs-out (open-output-file "/home/pcuser/Hermes/Hermes/conversations.txt" #:exists 'append)) -- cgit v1.2.3 From 63c4e2e1854deee38bdd655623a11d71a7bae6b6 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sat, 15 Apr 2017 21:06:14 -0400 Subject: client logs end with _client and server logs end with _server --- Hermes/TODO | 4 +--- Hermes/client.rkt | 10 ++++++---- Hermes/server.rkt | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Hermes/TODO b/Hermes/TODO index f5f0a1c..6bd88b0 100644 --- a/Hermes/TODO +++ b/Hermes/TODO @@ -1,5 +1,4 @@ FEATURES -1. Create a racket module for commonly used functions 4. message parsable? 5. command parsable? 7. maybe fiddle around with irc library @@ -7,8 +6,7 @@ FEATURES 10. authentication for databases 11. user can ask for no of logged in users. Server has to pars e -12. Hide user's own input in command line -14. bye message prompt for clients +*14. bye message prompt for clients part of session stickiness *15. Session stickiness for clients. Log received comms to a local file. additionally save user details and prompt user to use defaults or create new ones diff --git a/Hermes/client.rkt b/Hermes/client.rkt index 9f20dc4..96f55b0 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -1,4 +1,6 @@ #lang racket + +(require "modules/general.rkt") (require math/base) ;; for random number generation ;; TODO clean up string message output and alignment ;; i.e. seconds and minutes hours specifically @@ -7,19 +9,19 @@ ;; notes: output may need to be aligned and formatted nicely - +; i could prompt for these instead (define host "10.0.0.160") ; internal home (define host2 "67.186.191.81") (define host3 "localhost") (define port-num 4321) -(define hermes-conf (open-output-file "./hermes.conf" #:exists'append)) +(define hermes-conf (open-output-file "./hermes_client.conf" #:exists'append)) (define hermes-conf-s (make-semaphore 1)) -(define convs-out (open-output-file "./convs.out" #:exists 'append)) +(define convs-out (open-output-file "./convs_client.out" #:exists 'append)) (define convs-out-s (make-semaphore 1)) -(define error-out (open-output-file "./error.out" #:exists 'append)) +(define error-out (open-output-file "./error_client.out" #:exists 'append)) (define error-out-s (make-semaphore 1)) ; custodian for client connections diff --git a/Hermes/server.rkt b/Hermes/server.rkt index a309ddc..ba2c1c2 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -76,8 +76,8 @@ (define messages-s (make-semaphore 1)) ;; control access to messages ; two files to store error messages, and channel conversations -(define error-out (open-output-file "/home/pcuser/Hermes/Hermes/error.txt" #:exists 'append)) -(define convs-out (open-output-file "/home/pcuser/Hermes/Hermes/conversations.txt" #:exists 'append)) +(define error-out (open-output-file "/home/pcuser/Hermes/Hermes/error_server.txt" #:exists 'append)) +(define convs-out (open-output-file "/home/pcuser/Hermes/Hermes/conversations_server.txt" #:exists 'append)) (define error-out-s (make-semaphore 1)) (define convs-out-s (make-semaphore 1)) ; TODO finish logging all error related messages to -- cgit v1.2.3 From a532a8cc71bd8e6522deed63237344a03768bafb Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sat, 15 Apr 2017 21:53:49 -0400 Subject: all output generated from client is now logged to appropriate _client files --- Hermes/TODO | 16 +++++++++------- Hermes/client.rkt | 22 +++++++++++++--------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Hermes/TODO b/Hermes/TODO index 6bd88b0..8135f57 100644 --- a/Hermes/TODO +++ b/Hermes/TODO @@ -1,15 +1,17 @@ FEATURES 4. message parsable? 5. command parsable? -7. maybe fiddle around with irc library 8. separate main running code from definitions -10. authentication for databases -11. user can ask for no of logged in users. Server has to pars -e +16. plain tcp -> ssl based +17. fix breaks for improper disconnects from clients +18. Add topics after project completion + +GOOD TO HAVE BUT NOT NECESSARY +7. maybe fiddle around with irc library (we leave this for future opl classes) no time got other classes *14. bye message prompt for clients part of session stickiness *15. Session stickiness for clients. Log received comms to a local file. additionally save user details and prompt user to use defaults or create new ones -16. plain tcp -> ssl based -17. fix breaks for improper disconnects from clients -18. Add topics after project completion +10. authentication for databases - to avoid dependencies this is left out +11. user can ask for no of logged in users. - server already reports + diff --git a/Hermes/client.rkt b/Hermes/client.rkt index 96f55b0..3589765 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -3,6 +3,7 @@ (require "modules/general.rkt") (require math/base) ;; for random number generation ;; TODO clean up string message output and alignment +;; TODO close ports after done ;; i.e. seconds and minutes hours specifically ;; author: Ibrahim Mkusa ;; about: print and read concurrently @@ -40,21 +41,21 @@ (define a (thread (lambda () - (displayln "Starting receiver thread.") + (displayln-safe "Starting receiver thread." error-out-s error-out) (let loop [] (receive-messages in) (sleep 1) (loop))))) (define t (thread (lambda () - (displayln "Starting sender thread.") + (displayln-safe "Starting sender thread." error-out-s error-out) (let loop [] (send-messages username out) (sleep 1) (loop))))) - (displayln "Now waiting for sender thread.") + (displayln-safe "Now waiting for sender thread." error-out-s error-out) (thread-wait t) ;; returns prompt back to drracket - (displayln "Closing client ports.") + (displayln-safe "Closing client ports." error-out-s error-out) (close-input-port in) (close-output-port out)) (custodian-shutdown-all main-client-cust)) @@ -71,11 +72,14 @@ ":" (number->string (date-second date-today)) " | ")) - ;; intelligent read, quits when user types in "quit" + ;; read, quits when user types in "quit" (define input (read-line)) + ; TODO /quit instead of quit (cond ((string=? input "quit") (displayln (string-append date-print username " signing out. See ya!") out) (flush-output out) + (close-output-port error-out) + (close-output-port convs-out) (exit))) (displayln (string-append date-print username ": " input) out) @@ -87,14 +91,14 @@ (define evt (sync/timeout 60 (read-line-evt in))) (cond [(eof-object? evt) - (displayln "Server connection closed.") + (displayln-safe "Server connection closed." error-out-s error-out) (custodian-shutdown-all main-client-cust) ;(exit) ] [(string? evt) - (displayln evt)] ; could time stamp here or to send message + (displayln-safe evt convs-out-s convs-out)] ; could time stamp here or to send message [else - (displayln (string-append "Nothing received from server for 2 minutes."))])) + (displayln-safe (string-append "Nothing received from server for 2 minutes.") convs-out-s convs-out)])) -(displayln "Starting client.") +(displayln-safe "Starting client." error-out-s error-out) (define stop (client 4321)) -- cgit v1.2.3 From 52edc75849a97ba2cdee96ade120eaf14a90258c Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 13:50:26 -0400 Subject: more readable names for some functions --- Hermes/TODO | 11 ++++++++--- Hermes/client.rkt | 5 +++++ Hermes/server.rkt | 27 +++++++++++++++++---------- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/Hermes/TODO b/Hermes/TODO index 8135f57..0e41901 100644 --- a/Hermes/TODO +++ b/Hermes/TODO @@ -1,10 +1,13 @@ FEATURES -4. message parsable? -5. command parsable? -8. separate main running code from definitions +5. command(whisper, color, quit, count, users), message parsable? 16. plain tcp -> ssl based 17. fix breaks for improper disconnects from clients 18. Add topics after project completion +** regexes to parse strings for different formats -related to 5 +** put into a list if necessary for manipulation + +** adjust sleep time on all to be 0.1 for more responsiveness +** better function names GOOD TO HAVE BUT NOT NECESSARY 7. maybe fiddle around with irc library (we leave this for future opl classes) no time got other classes @@ -14,4 +17,6 @@ additionally save user details and prompt user to use defaults or create new ones 10. authentication for databases - to avoid dependencies this is left out 11. user can ask for no of logged in users. - server already reports +even the list of users connected. +12. on connection server should also display list of users currently logged in diff --git a/Hermes/client.rkt b/Hermes/client.rkt index 3589765..c328095 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -16,6 +16,7 @@ (define host3 "localhost") (define port-num 4321) +; we won't need this. Just me being overzealous (define hermes-conf (open-output-file "./hermes_client.conf" #:exists'append)) (define hermes-conf-s (make-semaphore 1)) @@ -39,6 +40,10 @@ (displayln "What's your name?") (define username (read-line)) + ;send the username to the server (username in out) + (displayln username out) + (flush-output out) + (define a (thread (lambda () (displayln-safe "Starting receiver thread." error-out-s error-out) diff --git a/Hermes/server.rkt b/Hermes/server.rkt index ba2c1c2..aab2347 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -32,8 +32,8 @@ (define (make-connections connections) (define (null-cons?) (null? connections)) - (define (add in out) - (set! connections (append connections (list (list in out)))) + (define (add username in out) + (set! connections (append connections (list (list username in out)))) connections) (define (cons-list) connections) @@ -86,7 +86,7 @@ (parameterize ([current-custodian main-cust]) (define listener (tcp-listen port-no 5 #t)) (define (loop) - (accept-and-handle listener) + (receive-clients listener) (loop)) (displayln-safe "Starting up the listener." error-out-s error-out) (thread loop) @@ -108,10 +108,17 @@ (semaphore-post convs-out-s) (custodian-shutdown-all main-cust))) -(define (accept-and-handle listener) +(define (receive-clients listener) (define cust (make-custodian)) (parameterize ([current-custodian cust]) (define-values (in out) (tcp-accept listener)) + + ;TODO retrive user name for client here + ; do some error checking + (define username-evt (read-line-evt out)) + + + ; increment number of connections (semaphore-wait c-count-s) ((c-count 'increment)) @@ -126,12 +133,13 @@ (displayln-safe print-no-users convs-out-s convs-out) (flush-output out) (semaphore-wait connections-s) - ((c-connections 'add) in out) + ; TODO add in a username so we have (username input output) + ((c-connections 'add) username-evt in out) (semaphore-post connections-s) ; start a thread to deal with specific client and add descriptor value to the list of threads (define threadcom (thread (lambda () - (handle in out)))) ; comms between server and particular client + (chat_with_client in out)))) ; comms between server and particular client ;; Watcher thread: ;; kills current thread for waiting too long for connection from @@ -142,7 +150,7 @@ (sleep 1360) (custodian-shutdown-all cust))))) -(define (handle in out) +(define (chat_with_client in out) ; deals with queueing incoming messages for server to broadcast to all clients (define (something-to-say in) (define evt-t0 (sync/timeout 60 (read-line-evt in 'linefeed))) @@ -175,11 +183,11 @@ ; extracts output port from a list pair of input and output port (define (get-output-port ports) - (cadr ports)) + (caddr ports)) ; extracts input port (define (get-input-port ports) - (car ports)) + (cadr ports)) ; broadcasts received message from clients periodically ; TODO before broadcasting the message make sure the ports is still open @@ -199,6 +207,5 @@ (displayln "Message broadcasted"))]) (semaphore-post messages-s))) -; TODO move to its own file (define stop (serve 4321)) ;; start server then close with stop (displayln-safe "Server process started\n" error-out-s error-out) -- cgit v1.2.3 From 5d36ba1d5d56151442edf92f4521663af741fe8e Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 14:06:39 -0400 Subject: username now stored along with related input output ports --- Hermes/server.rkt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Hermes/server.rkt b/Hermes/server.rkt index aab2347..749d06d 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -115,7 +115,7 @@ ;TODO retrive user name for client here ; do some error checking - (define username-evt (read-line-evt out)) + (define username-evt (sync (read-line-evt in 'linefeed))) -- cgit v1.2.3 From 61e6c973179aa2392c13a7472fb66b4975ad6478 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 16:24:16 -0400 Subject: Clients can now whisper to each other /whisper --- Hermes/TODO | 2 +- Hermes/server.rkt | 49 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/Hermes/TODO b/Hermes/TODO index 0e41901..416162e 100644 --- a/Hermes/TODO +++ b/Hermes/TODO @@ -1,5 +1,5 @@ FEATURES -5. command(whisper, color, quit, count, users), message parsable? +5. command(whisper, count, users), message parsable? parse in the client side should do something similar for settings (color, quit) 16. plain tcp -> ssl based 17. fix breaks for improper disconnects from clients 18. Add topics after project completion diff --git a/Hermes/server.rkt b/Hermes/server.rkt index 749d06d..3685de0 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -150,6 +150,16 @@ (sleep 1360) (custodian-shutdown-all cust))))) +; whisper selector for the username and message +(define (whisper-info exp) + (cadr exp)) + +(define (whisper-to exp) + (caddr exp)) + +(define (whisper-message exp) + (cadddr exp)) + (define (chat_with_client in out) ; deals with queueing incoming messages for server to broadcast to all clients (define (something-to-say in) @@ -166,11 +176,36 @@ ;(exit) (kill-thread (current-thread))] [(string? evt-t0) - (semaphore-wait messages-s) - ; append the message to list of messages NO NEED done during broadcast - ; (displayln-safe evt-t0 convs-out-s convs-out) - ((c-messages 'add) evt-t0) - (semaphore-post messages-s)] + ; use regexes to evaluate received input from client + (define whisper (regexp-match #px"(.*)/whisper\\s+(\\w+)\\s+(.*)" evt-t0)) ; is client trying to whisper to someone + (define list-count (regexp-match #px"(^/list)\\s+(count).*" evt-t0)) ;; is client asking for number of logged in users + (define list-users (regexp-match #px"(^/list)\\s+(users).*" evt-t0)) ;; user names + (cond [whisper + (semaphore-wait connections-s) + ; get output port for user + (define that-user-ports + (first (filter + (lambda (ports) + (if (string=? (whisper-to whisper) (get-username ports)) + #t + #f)) + ((c-connections 'cons-list))))) + ; try to send that user the whisper + (if (port-closed? (get-output-port that-user-ports)) + (begin + (displayln "User is unavailable" out) + (flush-output out)) + (begin + (displayln (string-append (whisper-info whisper) (whisper-message whisper)) + (get-output-port that-user-ports)) + (flush-output (get-output-port that-user-ports)))) + (semaphore-post connections-s)] + [else + (displayln-safe evt-t0) + (semaphore-wait messages-s) + ; evaluate it . + ((c-messages 'add) evt-t0) + (semaphore-post messages-s)])] [else (displayln-safe "Timeout waiting. Nothing received from client")])) @@ -189,6 +224,10 @@ (define (get-input-port ports) (cadr ports)) +; extract username +(define (get-username ports) + (car ports)) + ; broadcasts received message from clients periodically ; TODO before broadcasting the message make sure the ports is still open ; no EOF if it is remove client from connections -- cgit v1.2.3 From ec7b9a644a62aed32b772b4af701e9280f589e41 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 16:48:51 -0400 Subject: clients can type in /list count to ask for number of logged in users --- Hermes/TODO | 4 +++- Hermes/server.rkt | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Hermes/TODO b/Hermes/TODO index 416162e..a1a92df 100644 --- a/Hermes/TODO +++ b/Hermes/TODO @@ -5,6 +5,8 @@ FEATURES 18. Add topics after project completion ** regexes to parse strings for different formats -related to 5 ** put into a list if necessary for manipulation +** sync/timeout to plain sync +** align code better for readability ** adjust sleep time on all to be 0.1 for more responsiveness ** better function names @@ -19,4 +21,4 @@ new ones 11. user can ask for no of logged in users. - server already reports even the list of users connected. 12. on connection server should also display list of users currently logged in - +** whispers aren't currently logged diff --git a/Hermes/server.rkt b/Hermes/server.rkt index 3685de0..3092770 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -178,8 +178,9 @@ [(string? evt-t0) ; use regexes to evaluate received input from client (define whisper (regexp-match #px"(.*)/whisper\\s+(\\w+)\\s+(.*)" evt-t0)) ; is client trying to whisper to someone - (define list-count (regexp-match #px"(^/list)\\s+(count).*" evt-t0)) ;; is client asking for number of logged in users - (define list-users (regexp-match #px"(^/list)\\s+(users).*" evt-t0)) ;; user names + (define list-count (regexp-match #px"(.*)/list\\s+count\\s*" evt-t0)) ;; is client asking for number of logged in users + (define list-users (regexp-match #px"(.*)/list\\s+users\\s+(.*)" evt-t0)) ;; user names + ; do something whether it was a message, a whisper, request for number of users and so on (cond [whisper (semaphore-wait connections-s) ; get output port for user @@ -200,6 +201,17 @@ (get-output-port that-user-ports)) (flush-output (get-output-port that-user-ports)))) (semaphore-post connections-s)] + [list-count + ;;should put a semaphore on connections + (semaphore-wait c-count-s) + (semaphore-wait connections-s) + (define no-of-users (string-append "Number of users in chat: " + (number->string ((c-count 'current-count))))) + (displayln no-of-users out) + (flush-output out) + (semaphore-post connections-s) + (semaphore-post c-count-s) + ] [else (displayln-safe evt-t0) (semaphore-wait messages-s) -- cgit v1.2.3 From 9e1f8c33d17189c6bdf4c4db9481c0c08ee12218 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 17:07:19 -0400 Subject: clients can type /list users to get usernames logged in --- Hermes/Makefile | 4 ++-- Hermes/server.rkt | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Hermes/Makefile b/Hermes/Makefile index eda5bbb..940b2a5 100644 --- a/Hermes/Makefile +++ b/Hermes/Makefile @@ -1,3 +1,3 @@ -# Remove idiotic save files +# Remove temporary files clean: - rm -rf *~ + rm -rf *~ *.out diff --git a/Hermes/server.rkt b/Hermes/server.rkt index 3092770..6314f3b 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -179,7 +179,7 @@ ; use regexes to evaluate received input from client (define whisper (regexp-match #px"(.*)/whisper\\s+(\\w+)\\s+(.*)" evt-t0)) ; is client trying to whisper to someone (define list-count (regexp-match #px"(.*)/list\\s+count\\s*" evt-t0)) ;; is client asking for number of logged in users - (define list-users (regexp-match #px"(.*)/list\\s+users\\s+(.*)" evt-t0)) ;; user names + (define list-users (regexp-match #px"(.*)/list\\s+users\\s*" evt-t0)) ;; user names ; do something whether it was a message, a whisper, request for number of users and so on (cond [whisper (semaphore-wait connections-s) @@ -212,6 +212,16 @@ (semaphore-post connections-s) (semaphore-post c-count-s) ] + [list-users + (semaphore-wait connections-s) + ; map over connections sending the username to the client + (displayln "Here is a list of users in chat." out) + (map + (lambda (ports) + (displayln (get-username ports) out)) + ((c-connections 'cons-list))) + (flush-output out) + (semaphore-post connections-s)] [else (displayln-safe evt-t0) (semaphore-wait messages-s) -- cgit v1.2.3 From 7e7edb4a54d18d7ee75a228b7f2209d99827449f Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 17:20:17 -0400 Subject: sleep delay interval setting now managed as a global variable --- Hermes/client.rkt | 5 +++-- Hermes/server.rkt | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Hermes/client.rkt b/Hermes/client.rkt index c328095..e50a37f 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -15,6 +15,7 @@ (define host2 "67.186.191.81") (define host3 "localhost") (define port-num 4321) +(define sleep-t 0.1) ; we won't need this. Just me being overzealous (define hermes-conf (open-output-file "./hermes_client.conf" #:exists'append)) @@ -49,14 +50,14 @@ (displayln-safe "Starting receiver thread." error-out-s error-out) (let loop [] (receive-messages in) - (sleep 1) + (sleep sleep-t) (loop))))) (define t (thread (lambda () (displayln-safe "Starting sender thread." error-out-s error-out) (let loop [] (send-messages username out) - (sleep 1) + (sleep sleep-t) (loop))))) (displayln-safe "Now waiting for sender thread." error-out-s error-out) (thread-wait t) ;; returns prompt back to drracket diff --git a/Hermes/server.rkt b/Hermes/server.rkt index 6314f3b..ee949f5 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -4,10 +4,11 @@ (require math/base) ;; for random number generation -;; globals (define welcome-message "Welcome to Hermes coms. Type your message below") (define successful-connection-m "Successfully connected to a client. Sending client a welcome message.") +(define sleep-t 0.1) + ; track number of connections with closure (define (make-count no-count) (define (increment) @@ -95,7 +96,7 @@ (thread (lambda () (displayln-safe "Broadcast thread started!\n") (let loopb [] - (sleep 0.5) ;; wait 0.5 secs before beginning to broadcast + (sleep sleep-t) ;; wait 0.5 secs before beginning to broadcast (broadcast) (loopb))))) (lambda () -- cgit v1.2.3 From 6680d7504b2b1c45a6cfd0049212e162c279e172 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 17:32:02 -0400 Subject: sync/timeout to plain sync. Its appropriate given the chat context --- Hermes/client.rkt | 2 +- Hermes/server.rkt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Hermes/client.rkt b/Hermes/client.rkt index e50a37f..8959b1c 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -94,7 +94,7 @@ ; receives input from server and displays it to stdout (define (receive-messages in) ; retrieve a message from server - (define evt (sync/timeout 60 (read-line-evt in))) + (define evt (sync (read-line-evt in))) (cond [(eof-object? evt) (displayln-safe "Server connection closed." error-out-s error-out) diff --git a/Hermes/server.rkt b/Hermes/server.rkt index ee949f5..5e5f546 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -164,7 +164,7 @@ (define (chat_with_client in out) ; deals with queueing incoming messages for server to broadcast to all clients (define (something-to-say in) - (define evt-t0 (sync/timeout 60 (read-line-evt in 'linefeed))) + (define evt-t0 (sync (read-line-evt in 'linefeed))) (cond [(eof-object? evt-t0) (semaphore-wait connections-s) ((c-connections 'remove-ports) in out) @@ -224,7 +224,7 @@ (flush-output out) (semaphore-post connections-s)] [else - (displayln-safe evt-t0) + ; (displayln-safe evt-t0) debug purposes (semaphore-wait messages-s) ; evaluate it . ((c-messages 'add) evt-t0) -- cgit v1.2.3 From f10fb083cda715faba8d5aab40dbcf9ab0d501c1 Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 17:47:42 -0400 Subject: broadcast now checks whether port is open before trying to send --- Hermes/TODO | 11 ++--------- Hermes/client.rkt | 6 +++--- Hermes/server.rkt | 9 ++++++--- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/Hermes/TODO b/Hermes/TODO index a1a92df..bbc2930 100644 --- a/Hermes/TODO +++ b/Hermes/TODO @@ -1,15 +1,11 @@ FEATURES -5. command(whisper, count, users), message parsable? parse in the client side should do something similar for settings (color, quit) +5. parser in the client side should do something similar (/color, /quit) 16. plain tcp -> ssl based 17. fix breaks for improper disconnects from clients 18. Add topics after project completion ** regexes to parse strings for different formats -related to 5 -** put into a list if necessary for manipulation -** sync/timeout to plain sync ** align code better for readability -** adjust sleep time on all to be 0.1 for more responsiveness -** better function names GOOD TO HAVE BUT NOT NECESSARY 7. maybe fiddle around with irc library (we leave this for future opl classes) no time got other classes @@ -18,7 +14,4 @@ GOOD TO HAVE BUT NOT NECESSARY additionally save user details and prompt user to use defaults or create new ones 10. authentication for databases - to avoid dependencies this is left out -11. user can ask for no of logged in users. - server already reports -even the list of users connected. -12. on connection server should also display list of users currently logged in -** whispers aren't currently logged +** whispers aren't currently logged - its on purpose diff --git a/Hermes/client.rkt b/Hermes/client.rkt index 8959b1c..0e3c986 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -10,8 +10,8 @@ ;; notes: output may need to be aligned and formatted nicely -; i could prompt for these instead -(define host "10.0.0.160") ; internal home +; we will prompt for these in the gui +(define host "10.0.0.160") (define host2 "67.186.191.81") (define host3 "localhost") (define port-num 4321) @@ -107,4 +107,4 @@ (displayln-safe (string-append "Nothing received from server for 2 minutes.") convs-out-s convs-out)])) (displayln-safe "Starting client." error-out-s error-out) -(define stop (client 4321)) +(define stop-client (client 4321)) diff --git a/Hermes/server.rkt b/Hermes/server.rkt index 5e5f546..df1cf26 100644 --- a/Hermes/server.rkt +++ b/Hermes/server.rkt @@ -260,8 +260,11 @@ (cond [(not (null? ((c-messages 'mes-list)))) (begin (map (lambda (ports) - (displayln (first ((c-messages 'mes-list))) (get-output-port ports)) - (flush-output (get-output-port ports))) + (if (not (port-closed? (get-output-port ports))) + (begin + (displayln (first ((c-messages 'mes-list))) (get-output-port ports)) + (flush-output (get-output-port ports))) + (displayln-safe "Failed to broadcast. Port not open." error-out-s error-out))) ((c-connections 'cons-list))) (displayln-safe (first ((c-messages 'mes-list))) convs-out-s convs-out) ;; remove top message @@ -269,5 +272,5 @@ (displayln "Message broadcasted"))]) (semaphore-post messages-s))) -(define stop (serve 4321)) ;; start server then close with stop +(define stop-server (serve 4321)) ;; start server then close with stop (displayln-safe "Server process started\n" error-out-s error-out) -- cgit v1.2.3 From ed029f79066c8566e313794a6f66ae4c73614acc Mon Sep 17 00:00:00 2001 From: Ibrahim Mkusa Date: Sun, 16 Apr 2017 18:19:00 -0400 Subject: minor additions --- Hermes/Makefile | 2 +- Hermes/client.rkt | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Hermes/Makefile b/Hermes/Makefile index 940b2a5..fdd9a07 100644 --- a/Hermes/Makefile +++ b/Hermes/Makefile @@ -1,3 +1,3 @@ # Remove temporary files clean: - rm -rf *~ *.out + rm -rf *~ *.out *.conf diff --git a/Hermes/client.rkt b/Hermes/client.rkt index 0e3c986..d4ad2a0 100644 --- a/Hermes/client.rkt +++ b/Hermes/client.rkt @@ -11,8 +11,6 @@ ; we will prompt for these in the gui -(define host "10.0.0.160") -(define host2 "67.186.191.81") (define host3 "localhost") (define port-num 4321) (define sleep-t 0.1) -- cgit v1.2.3