STDJ Interface
From Hang The DJ
The STDJ interface is accessed through the Friends dlg bar and the Connections options.
HOW A USER CONNECTS TO A SERVER
- The user first needs to go to the Connections options and add a server.
- The user will need the url and port of the server.
- To connect to the server, the user will have to provide a username and password to register.
- Once the user is registered, the Connections options page will display the connection status, which is constantly updated based on heartbeat data.
- The user will be able to ask the server questions, which the server may answer, or which the server may pass on to other clients.
SERVER REGISTRATION HANDLING
- The server tracks client requests. The first request from a client must always include username/password.
- The server maintains a persistent username/password-hash list.
- If the incoming request is validated against the persistent list, the heartbeat is returned.
- If the incoming request is a NEW username, the username/password-hash is added to the persistent list. This needs to be updated to restrict new users as needed.
- If the incoming request is for an existing username with the WRONG password, reject the user connection.
SERVER MESSAGE HANDLING
- server maintains queue of questions and queue of answers to be sent out
- server is simply a q/a gateway, passing them on as requested - there is typically no need for SERVER to match q type to a type
- the exception to this rule is "file part" messages - only respond with a "file part" answer when receiving a specific request for that file
- some questions are meant for the server (users, subscribe, heartbeat); in this case, answers are immediately returned to the sender of the question
TRANSFERRED OBJECTS
- All communication from client to server and server to client takes place via Transferred Objects (TO).
- A TO contains the u/p of the sender, a list of questions, and a list of answers.
- Use case:
- ClientA sends Q to server
- Server caches Q and waits for ping from ClientB
- ClientB sends ping to server
- Server sends Q to ClientB
- ClientB receives Q from server
- ClientB sends A to server
- Server caches A and waits for ping from ClientA
- ClientA sends ping to server
- Server sends A to ClientA
CLASS DESCRIPTIONS
class purpose(s)
stdjinterface manages vector of servers
load/register/login/add/remove
NOTE: we dynamically allocate servers and
use a vector of pointers to avoid
problems copying server objects
(and the threads (etc) they contain)
one-stop for registering notification windows
msg broadcasts
SendPlaylist, SendNextSong, UpdateConnectedUsers
request from server
RequestFiles, RequestPlaylist
RequestPlaylistUnsubscribe (no implementation!)
send to server
add to queue, fire thread event
stdjset "light" ~wizard-maintained server db info class
stdjserver handle u/p issues
track all threads
stdjthread base thread
handles heartbeats, all q&a except chunks
TRANSFER COMMUNICATION FLOW
transfer a file
right-click in friend list
select "Play" (IDC_FRIEND_SONG_PLAY)
FriendSongList::OnFriendSongPlay()
m_pPlayDlg->stdj.RequestFiles()
--
toSending.CreateFilesRequest( pSU->m_strUser, toq_type, vfdRequestedSongs );
SendToServer( svr, toSending );
svr.DownloadFile( pSU->m_strUser, *itFile, toq_type );
--
m_vDownloadThreads.back().StartDownload( this, strUserSendingFile, fd, toq_type );
--
SetDownloadNotificationWnd( m_pSvr->m_pPlayDlg->m_pTransferList->GetSafeHwnd() );
::PostMessage( m_hDownloadNotificationWnd, WM_USER_INIT_DOWNLOAD, (WPARAM)pstrFilename_new, 0L )
->CHANGE THIS, NO NEED TO POST HERE! We're still in the main thread.
Start();
--
(new thread)
--
STDJThread::Main()
WaitForEvent
case TransferredAnswer::TOA_NEXT_FILE_PART:
ProcessDownload( *itUA );
--
m_pFileStream->write( &ua.m_ta.FileBuffer()[0], ua.m_ta.ChunkSize() );
if ( ua.m_ta.StartByte() + ua.m_ta.ChunkSize() == m_nFileSize )
(end the transfer)
else
(update the transfer status)
(back in the main thread)
TransferList::OnInitDownload() (WM_USER_INIT_DOWNLOAD handler)
InsertDownload( *pstrFilename );
--
return InsertItem( -1, strFilename.c_str() );