47 |
|
|
48 |
namespace LinuxSampler { |
namespace LinuxSampler { |
49 |
|
|
50 |
|
String lscpParserProcessShellInteraction(String& line, yyparse_param_t* param); |
51 |
|
|
52 |
/** |
/** |
53 |
* Returns a copy of the given string where all special characters are |
* Returns a copy of the given string where all special characters are |
54 |
* replaced by LSCP escape sequences ("\xHH"). This function shall be used |
* replaced by LSCP escape sequences ("\xHH"). This function shall be used |
594 |
//Something was selected and it was not the hSocket, so it must be some command(s) coming. |
//Something was selected and it was not the hSocket, so it must be some command(s) coming. |
595 |
for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) { |
for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) { |
596 |
if (FD_ISSET((*iter).hSession, &selectSet)) { //Was it this socket? |
if (FD_ISSET((*iter).hSession, &selectSet)) { //Was it this socket? |
597 |
|
currentSocket = (*iter).hSession; //a hack |
598 |
if (GetLSCPCommand(iter)) { //Have we read the entire command? |
if (GetLSCPCommand(iter)) { //Have we read the entire command? |
599 |
dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket)); |
dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket)); |
600 |
int dummy; // just a temporary hack to fulfill the restart() function prototype |
int dummy; // just a temporary hack to fulfill the restart() function prototype |
601 |
restart(NULL, dummy); // restart the 'scanner' |
restart(NULL, dummy); // restart the 'scanner' |
|
currentSocket = (*iter).hSession; //a hack |
|
602 |
itCurrentSession = iter; // another hack |
itCurrentSession = iter; // another hack |
603 |
dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str())); |
dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str())); |
604 |
if ((*iter).bVerbose) { // if echo mode enabled |
if ((*iter).bVerbose) { // if echo mode enabled |
612 |
CloseConnection(iter); |
CloseConnection(iter); |
613 |
} |
} |
614 |
} |
} |
615 |
|
currentSocket = -1; //continuation of a hack |
616 |
//socket may have been closed, iter may be invalid, get out of the loop for now. |
//socket may have been closed, iter may be invalid, get out of the loop for now. |
617 |
//we'll be back if there is data. |
//we'll be back if there is data. |
618 |
break; |
break; |
742 |
bufferedCommands[socket] += "\r\n"; |
bufferedCommands[socket] += "\r\n"; |
743 |
return true; //Complete command was read |
return true; //Complete command was read |
744 |
} |
} |
745 |
bufferedCommands[socket] += c; |
// backspace character - should only happen with shell |
746 |
|
if (c == '\b') { |
747 |
|
if (!bufferedCommands[socket].empty()) { |
748 |
|
bufferedCommands[socket] = bufferedCommands[socket].substr( |
749 |
|
0, bufferedCommands[socket].length() - 1 |
750 |
|
); |
751 |
|
} |
752 |
|
} else bufferedCommands[socket] += c; |
753 |
|
// only if the other side is the LSCP shell application: |
754 |
|
// check the current (incomplete) command line for syntax errors, |
755 |
|
// possible completions and report everything back to the shell |
756 |
|
if ((*iter).bShellInteract) { |
757 |
|
String s = lscpParserProcessShellInteraction(bufferedCommands[socket], &(*iter)); |
758 |
|
if (!s.empty()) AnswerClient(s + "\n"); |
759 |
|
} |
760 |
} |
} |
761 |
#if defined(WIN32) |
#if defined(WIN32) |
762 |
if (result == SOCKET_ERROR) { |
if (result == SOCKET_ERROR) { |
818 |
* @param ReturnMessage - message that will be send to the client |
* @param ReturnMessage - message that will be send to the client |
819 |
*/ |
*/ |
820 |
void LSCPServer::AnswerClient(String ReturnMessage) { |
void LSCPServer::AnswerClient(String ReturnMessage) { |
821 |
dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str())); |
dmsg(2,("LSCPServer::AnswerClient(ReturnMessage='%s')", ReturnMessage.c_str())); |
822 |
if (currentSocket != -1) { |
if (currentSocket != -1) { |
823 |
LockGuard lock(NotifyMutex); |
LockGuard lock(NotifyMutex); |
824 |
|
|
825 |
|
// just if other side is LSCP shell: in case respose is a multi-line |
826 |
|
// one, then inform client about it before sending the actual mult-line |
827 |
|
// response |
828 |
|
if (GetCurrentYaccSession()->bShellInteract) { |
829 |
|
// check if this is a multi-line response |
830 |
|
int n = 0; |
831 |
|
for (int i = 0; i < ReturnMessage.size(); ++i) |
832 |
|
if (ReturnMessage[i] == '\n') ++n; |
833 |
|
if (n >= 2) { |
834 |
|
dmsg(2,("LSCP Shell <- expect mult-line response\n")); |
835 |
|
String s = LSCP_SHK_EXPECT_MULTI_LINE "\r\n"; |
836 |
|
#ifdef MSG_NOSIGNAL |
837 |
|
send(currentSocket, s.c_str(), s.size(), MSG_NOSIGNAL); |
838 |
|
#else |
839 |
|
send(currentSocket, s.c_str(), s.size(), 0); |
840 |
|
#endif |
841 |
|
} |
842 |
|
} |
843 |
|
|
844 |
#ifdef MSG_NOSIGNAL |
#ifdef MSG_NOSIGNAL |
845 |
send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL); |
send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL); |
846 |
#else |
#else |
3996 |
} |
} |
3997 |
return result.Produce(); |
return result.Produce(); |
3998 |
} |
} |
3999 |
|
|
4000 |
|
String LSCPServer::SetShellInteract(yyparse_param_t* pSession, double boolean_value) { |
4001 |
|
dmsg(2,("LSCPServer: SetShellInteract(val=%f)\n", boolean_value)); |
4002 |
|
LSCPResultSet result; |
4003 |
|
try { |
4004 |
|
if (boolean_value == 0) pSession->bShellInteract = false; |
4005 |
|
else if (boolean_value == 1) pSession->bShellInteract = true; |
4006 |
|
else throw Exception("Not a boolean value, must either be 0 or 1"); |
4007 |
|
} catch (Exception e) { |
4008 |
|
result.Error(e); |
4009 |
|
} |
4010 |
|
return result.Produce(); |
4011 |
|
} |
4012 |
|
|
4013 |
} |
} |