diff --git a/src/minidexed.cpp b/src/minidexed.cpp index 1e925ed..4a4ce46 100644 --- a/src/minidexed.cpp +++ b/src/minidexed.cpp @@ -1123,6 +1123,7 @@ void CMiniDexed::SetTGParameter (TTGParameter Parameter, int nValue, unsigned nT case TGParameterATAmplitude: setModController(3, 2, nValue, nTG); break; case TGParameterATEGBias: setModController(3, 3, nValue, nTG); break; + case TGParameterMIDIChannel: assert (0 <= nValue && nValue <= 255); SetMIDIChannel ((uint8_t) nValue, nTG); @@ -2306,7 +2307,7 @@ void CMiniDexed::UpdateNetwork() } if (m_pConfig->GetNetworkFTPEnabled()) { - m_pFTPDaemon = new CFTPDaemon(FTPUSERNAME, FTPPASSWORD); + m_pFTPDaemon = new CFTPDaemon(FTPUSERNAME, FTPPASSWORD, m_pmDNSPublisher, m_pConfig); if (!m_pFTPDaemon->Initialize()) { diff --git a/src/net/applemidi.cpp b/src/net/applemidi.cpp index e14b216..82014e1 100644 --- a/src/net/applemidi.cpp +++ b/src/net/applemidi.cpp @@ -457,7 +457,7 @@ bool ParseMIDIPacket(const u8* pBuffer, size_t nSize, TRTPMIDI* pOutPacket, CApp return ParseMIDICommandSection(pMIDICommandSection, nRemaining, pHandler); } -CAppleMIDIParticipant::CAppleMIDIParticipant(CBcmRandomNumberGenerator* pRandom, CAppleMIDIHandler* pHandler) +CAppleMIDIParticipant::CAppleMIDIParticipant(CBcmRandomNumberGenerator* pRandom, CAppleMIDIHandler* pHandler, const char* pSessionName) : CTask(TASK_STACK_SIZE, true), m_pRandom(pRandom), @@ -489,7 +489,9 @@ CAppleMIDIParticipant::CAppleMIDIParticipant(CBcmRandomNumberGenerator* pRandom, m_nSequence(0), m_nLastFeedbackSequence(0), - m_nLastFeedbackTime(0) + m_nLastFeedbackTime(0), + + m_pSessionName(pSessionName) { } @@ -802,8 +804,11 @@ bool CAppleMIDIParticipant::SendAcceptInvitationPacket(CSocket* pSocket, CIPAddr {'\0'} }; - // TODO: configurable name - strncpy(AcceptPacket.Name, "MiniDexed", sizeof(AcceptPacket.Name)); + // Use hostname as the session name + if (m_pSessionName && m_pSessionName[0]) + strncpy(AcceptPacket.Name, m_pSessionName, sizeof(AcceptPacket.Name)); + else + strncpy(AcceptPacket.Name, "MiniDexed", sizeof(AcceptPacket.Name)); #ifdef APPLEMIDI_DEBUG LOGNOTE("--> Accept invitation"); diff --git a/src/net/applemidi.h b/src/net/applemidi.h index 3df68ae..a774592 100644 --- a/src/net/applemidi.h +++ b/src/net/applemidi.h @@ -39,7 +39,7 @@ public: class CAppleMIDIParticipant : protected CTask { public: - CAppleMIDIParticipant(CBcmRandomNumberGenerator* pRandom, CAppleMIDIHandler* pHandler); + CAppleMIDIParticipant(CBcmRandomNumberGenerator* pRandom, CAppleMIDIHandler* pHandler, const char* pSessionName); virtual ~CAppleMIDIParticipant() override; bool Initialize(); @@ -106,6 +106,8 @@ private: u16 m_nSequence = 0; u16 m_nLastFeedbackSequence = 0; u64 m_nLastFeedbackTime = 0; + + const char* m_pSessionName; }; #endif \ No newline at end of file diff --git a/src/net/ftpdaemon.cpp b/src/net/ftpdaemon.cpp index 0cab51c..015dbc9 100644 --- a/src/net/ftpdaemon.cpp +++ b/src/net/ftpdaemon.cpp @@ -34,11 +34,13 @@ LOGMODULE("ftpd"); constexpr u16 ListenPort = 21; constexpr u8 MaxConnections = 1; -CFTPDaemon::CFTPDaemon(const char* pUser, const char* pPassword) +CFTPDaemon::CFTPDaemon(const char* pUser, const char* pPassword, CmDNSPublisher* pMDNSPublisher, CConfig* pConfig) : CTask(TASK_STACK_SIZE, true), m_pListenSocket(nullptr), m_pUser(pUser), - m_pPassword(pPassword) + m_pPassword(pPassword), + m_pmDNSPublisher(pMDNSPublisher), + m_pConfig(pConfig) { } @@ -106,6 +108,6 @@ void CFTPDaemon::Run() } // Spawn new worker - new CFTPWorker(pConnection, m_pUser, m_pPassword); + new CFTPWorker(pConnection, m_pUser, m_pPassword, m_pmDNSPublisher, m_pConfig); } } \ No newline at end of file diff --git a/src/net/ftpdaemon.h b/src/net/ftpdaemon.h index 4d75762..77afb14 100644 --- a/src/net/ftpdaemon.h +++ b/src/net/ftpdaemon.h @@ -25,11 +25,13 @@ #include #include +#include "mdnspublisher.h" +#include "../config.h" class CFTPDaemon : protected CTask { public: - CFTPDaemon(const char* pUser, const char* pPassword); + CFTPDaemon(const char* pUser, const char* pPassword, CmDNSPublisher* pMDNSPublisher, CConfig* pConfig); virtual ~CFTPDaemon() override; bool Initialize(); @@ -42,6 +44,8 @@ private: const char* m_pUser; const char* m_pPassword; + CmDNSPublisher* m_pmDNSPublisher; + CConfig* m_pConfig; }; #endif \ No newline at end of file diff --git a/src/net/ftpworker.cpp b/src/net/ftpworker.cpp index 28415e2..a19cfde 100644 --- a/src/net/ftpworker.cpp +++ b/src/net/ftpworker.cpp @@ -126,7 +126,7 @@ inline bool DirectoryCaseInsensitiveAscending(const TDirectoryListEntry& EntryA, } -CFTPWorker::CFTPWorker(CSocket* pControlSocket, const char* pExpectedUser, const char* pExpectedPassword) +CFTPWorker::CFTPWorker(CSocket* pControlSocket, const char* pExpectedUser, const char* pExpectedPassword, CmDNSPublisher* pMDNSPublisher, CConfig* pConfig) : CTask(TASK_STACK_SIZE), m_LogName(), m_pExpectedUser(pExpectedUser), @@ -142,7 +142,9 @@ CFTPWorker::CFTPWorker(CSocket* pControlSocket, const char* pExpectedUser, const m_DataType(TDataType::ASCII), m_TransferMode(TTransferMode::Active), m_CurrentPath(), - m_RenameFrom() + m_RenameFrom(), + m_pmDNSPublisher(pMDNSPublisher), + m_pConfig(pConfig) { ++s_nInstanceCount; m_LogName.Format("ftpd[%d]", s_nInstanceCount); @@ -562,7 +564,7 @@ bool CFTPWorker::Passive(const char* pArgs) IPAddress[2], IPAddress[3], (m_nDataSocketPort >> 8) & 0xFF, - m_nDataSocketPort & 0xFF + (m_nDataSocketPort & 0xFF) ); SendStatus(TFTPStatus::EnteringPassiveMode, Buffer); @@ -1058,9 +1060,24 @@ bool CFTPWorker::Bye(const char* pArgs) SendStatus(TFTPStatus::ClosingControl, "Goodbye."); delete m_pControlSocket; m_pControlSocket = nullptr; - + + // Unpublish the mDNS services + if (m_pmDNSPublisher && m_pConfig) + { + m_pmDNSPublisher->UnpublishService(m_pConfig->GetNetworkHostname()); + m_pmDNSPublisher->UnpublishService(m_pConfig->GetNetworkHostname(), CmDNSPublisher::ServiceTypeAppleMIDI, 5004); + m_pmDNSPublisher->UnpublishService(m_pConfig->GetNetworkHostname(), CmDNSPublisher::ServiceTypeFTP, 21); + } + + // Non-blocking 2 second delay before reboot + CTimer* const pTimer = CTimer::Get(); + unsigned int start = pTimer->GetTicks(); + while ((pTimer->GetTicks() - start) < 2 * HZ) { + CScheduler::Get()->Yield(); + } + // Reboot the system if the user disconnects in order to apply any changes made - reboot (); + reboot(); return true; } diff --git a/src/net/ftpworker.h b/src/net/ftpworker.h index 62e60ed..17abfda 100644 --- a/src/net/ftpworker.h +++ b/src/net/ftpworker.h @@ -27,6 +27,8 @@ #include #include #include +#include "../config.h" +#include "mdnspublisher.h" // TODO: These may be incomplete/inaccurate enum TFTPStatus @@ -79,7 +81,7 @@ struct TDirectoryListEntry; class CFTPWorker : protected CTask { public: - CFTPWorker(CSocket* pControlSocket, const char* pExpectedUser, const char* pExpectedPassword); + CFTPWorker(CSocket* pControlSocket, const char* pExpectedUser, const char* pExpectedPassword, CmDNSPublisher* pMDNSPublisher, CConfig* pConfig); virtual ~CFTPWorker() override; virtual void Run() override; @@ -142,6 +144,9 @@ private: CString m_CurrentPath; CString m_RenameFrom; + CmDNSPublisher* m_pmDNSPublisher; + CConfig* m_pConfig; + static void FatFsPathToFTPPath(const char* pInBuffer, char* pOutBuffer, size_t nSize); static void FTPPathToFatFsPath(const char* pInBuffer, char* pOutBuffer, size_t nSize); diff --git a/src/net/mdnspublisher.cpp b/src/net/mdnspublisher.cpp index fbeb549..49ae79b 100644 --- a/src/net/mdnspublisher.cpp +++ b/src/net/mdnspublisher.cpp @@ -131,6 +131,45 @@ boolean CmDNSPublisher::UnpublishService (const char *pServiceName) delete pService; return TRUE; } +boolean CmDNSPublisher::UnpublishService(const char *pServiceName, const char *pServiceType, u16 usServicePort) +{ + if (!m_bRunning) + { + return FALSE; + } + assert(pServiceName); + assert(pServiceType); + m_Mutex.Acquire(); + TService *pService = nullptr; + TPtrListElement *pElement = m_ServiceList.GetFirst(); + while (pElement) + { + pService = static_cast(CPtrList::GetPtr(pElement)); + assert(pService); + if (pService->ServiceName.Compare(pServiceName) == 0 && + pService->ServiceType.Compare(pServiceType) == 0 && + pService->usServicePort == usServicePort) + { + m_ServiceList.Remove(pElement); + break; + } + pService = nullptr; + pElement = m_ServiceList.GetNext(pElement); + } + m_Mutex.Release(); + if (!pService) + { + return FALSE; + } + LOGDBG("Unpublish service %s %s %u", (const char *)pService->ServiceName, (const char *)pService->ServiceType, pService->usServicePort); + SendResponse(pService, FALSE); + for (unsigned i = 0; i < pService->nTextRecords; i++) + { + delete pService->ppText[i]; + } + delete pService; + return TRUE; +} void CmDNSPublisher::Run (void) { assert (m_pNet); diff --git a/src/net/mdnspublisher.h b/src/net/mdnspublisher.h index 6b132a7..c26f6ea 100644 --- a/src/net/mdnspublisher.h +++ b/src/net/mdnspublisher.h @@ -32,6 +32,7 @@ class CmDNSPublisher : public CTask /// mDNS / Bonjour client task { public: static constexpr const char *ServiceTypeAppleMIDI = "_apple-midi._udp"; + static constexpr const char *ServiceTypeFTP = "_ftp._tcp"; public: /// \param pNet Pointer to the network subsystem object CmDNSPublisher (CNetSubSystem *pNet); @@ -50,6 +51,12 @@ public: /// \param pServiceName Name of the service to be unpublished (same as when published) /// \return Operation successful? boolean UnpublishService (const char *pServiceName); + /// \brief Stop publishing a service + /// \param pServiceName Name of the service to be unpublished + /// \param pServiceType Type of the service to be unpublished + /// \param usServicePort Port number of the service to be unpublished + /// \return Operation successful? + boolean UnpublishService (const char *pServiceName, const char *pServiceType, u16 usServicePort); void Run (void) override; private: static const unsigned MaxTextRecords = 10; diff --git a/src/udpmididevice.cpp b/src/udpmididevice.cpp index 4b0d1c7..1934e42 100644 --- a/src/udpmididevice.cpp +++ b/src/udpmididevice.cpp @@ -46,7 +46,7 @@ CUDPMIDIDevice::~CUDPMIDIDevice (void) boolean CUDPMIDIDevice::Initialize (void) { - m_pAppleMIDIParticipant = new CAppleMIDIParticipant(&m_Random, this); + m_pAppleMIDIParticipant = new CAppleMIDIParticipant(&m_Random, this, m_pConfig->GetNetworkHostname()); if (!m_pAppleMIDIParticipant->Initialize()) { LOGERR("Failed to init RTP listener");