/** Initialize an OSC-message with a raw byte-stream * (for instance from a network receiver). * The message object is reassembled from binary data. The length * must be known. When successfully reassembled, the arguments * (when existing) are accessable via the getNumXXX() and getXXX(int idx) * interface functions. * * \param buffer * Packet data containing the whole message with arguments. * * \param bufferLen * Packet data length. * * \throws WOscException * When corrupt initialization data, inconsistent bufferlengths etc. found. * * \todo Since a message is defined, when its beginning is known * creating it from a byte stream without knowing the length would be * possible. Write an initializer. * * \remarks * If an exception occurs, the construction of the message will be * aborted, including the arguments. * * \todo * Add intensive exception handling for corrupt init data * * \see * WOscException | WOscString */ WOscMessage::WOscMessage(const char* buffer, int bufferLen){ m_floats = NULL; m_numFloats = 0; m_ints = NULL; m_numInts = 0; m_strings = NULL; m_numStrings = 0; m_blobs = NULL; m_numBlobs = 0; m_buffer = NULL; // check address if (bufferLen < 1) throw new WOscException( WOscException::ERR_NULL_BUFFER, "WOscMessage: Message initialization buffer is empty."); // check address if (buffer[0] != '/') throw new WOscException( WOscException::ERR_INVALID_ADDRESS_NO_SLASH, "WOscMessage: Message address corrupt, no slash."); // extract address m_address = buffer; // get type tag int pos = m_address.GetSize(); m_typeTag = W_OSC_EMPTY_TYPE_TAG; // init type tag if (bufferLen <= pos){ // no type tag in buffer -> leave empty type tag GenerateBufferFromMembers(); return; } WOscString OscTypeTag = buffer + pos; // get args by scanning typetag string const char* typeTag = OscTypeTag.GetBuffer(); int typeTagSize = OscTypeTag.GetSize(); pos += typeTagSize; // offset in buffer (beginning of argument data) for ( int i = 0; i < typeTagSize; i++ ){ switch (typeTag[i]){ case 'i': Add(WOscUtil::CharBufToInt(buffer + pos)); pos += WOscUtil::OSC_INT_SIZE; break; case 'f': Add(WOscUtil::CharBufToFloat(buffer + pos)); pos += WOscUtil::OSC_FLOAT_SIZE; break; case 's': Add(buffer+pos); pos += m_strings[m_numStrings-1].GetSize(); break; case 'b':{ WOscBlob* blob = new WOscBlob(buffer + pos); Add( blob ); pos += blob->GetBufferLen(); delete blob; break; } case ',': break; case '\0': i = typeTagSize; // jump to end break; default: // error i = typeTagSize; // jump to end break; } } GenerateBufferFromMembers(); // generate arrays of arguments for later use with getXXX(int idx) }
int main() { const char* default_serverurl = "localhost"; short default_serverport = 7554; bool threading = false; WOscStreamingClient client(threading); // // Setup OSC address space // // containers WOscContainer* cntRoot = new WOscContainer(); WOscContainer* cntTest = new WOscContainer(cntRoot, "test"); // "root" methods WOscMethod* msgEcho = new WOscTcpHandlerMethod(cntRoot, &client, "printed", "printed description."); msgEcho->AddMethodAlias(cntTest, "echo"); // add alias of method to same container where the original resides (to test the clean up) msgEcho->AddMethodAlias(cntTest, "echo2"); // add alias of container to same container where the original resides (to test the clean up) cntTest->AddContainerAlias(cntRoot, "test2"); client.SetAddressSpace(cntRoot); WOscString addressSpaceStr = cntRoot->GetAddressSpace(); std::cout<<"Client address space:\n"<<addressSpaceStr.GetBuffer()<<std::flush; // // Connect to server // TheNetReturnAddress serverAddress; serverAddress.m_addr.sin_family = AF_INET; serverAddress.m_addr.sin_port = htons(default_serverport); if ( resolve(serverAddress.m_addr.sin_addr, default_serverurl) ) { std::cout<<"Resolved \""<<default_serverurl<<"\" successfully."<<std::endl; } else { std::cout<<"Failed to resolve \""<<default_serverurl<<"\". Defaulting to 127.0.0.1"<<std::endl; default_serverurl = "127.0.0.1"; serverAddress.m_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); } std::cout<<"Connecting to \""<<default_serverurl<<"\" ("<<*inet_ntoa(serverAddress.m_addr.sin_addr) <<")."<<std::endl; WOscTcpClient::Error clientError = client.Connect(serverAddress); if ( clientError != WOscTcpClient::WOS_ERR_NO_ERROR ) { std::cout<<"Client connect failed with: "<<WOscTcpClient::GetErrStr(clientError)<<std::endl; return -1; } std::cout<<"Connected. Entering mainloop."<<std::endl; // // Main loop // WOscBundle theBundle; bool bundleOpen = false; while ( true ) { char input[1024]; if ( threading ) { std::cin.getline(input,1024,'\n'); } else { fd_set rfds; struct timeval tv; int retval; /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); FD_SET(0, &rfds); FD_SET(client.GetSocketID(), &rfds); /* Wait up to five seconds. */ tv.tv_sec = 0; tv.tv_usec = 0; retval = select(client.GetSocketID()+1, &rfds, NULL, NULL, NULL/*&tv*/); /* Don't rely on the value of tv now! */ if (retval == -1) { perror("select()"); break; } else if (retval) { if ( FD_ISSET(0, &rfds) ) { std::cin.getline(input,1024,'\n'); } else if ( FD_ISSET(client.GetSocketID(), &rfds) ) { WOscTcpClient::Error err = client.NetworkReceive(); if ( err == WOscTcpClient::WOS_ERR_NO_ERROR ) continue; else if ( err == WOscTcpClient::WOS_ERR_CONNECTION_CLOSED ) { std::cout<<"Connection has been closed by peer."<<std::endl; break; } else { std::cout<<"Connection failure on receive."<<std::endl; break; } } else { std::cout<<"No file descriptor for this select."<<std::endl; break; } } else { printf("Select timeout.\n"); continue; } } if ( input[0] == '/' ) { // message assembly try { // parse parameters char* params[100]; int nParams = 0; char* next = strchr ( input, ' ' ); while ( next != 0 || nParams >= 100 ) { // add parameter to list params[nParams] = next + 1; // and zero-terminate previous *next = 0; // try to find new parameter next = strchr ( params[nParams++], ' ' ); } // assemble message WOscMessage msg(input); // add parameters for ( int i = 0; i < nParams; i++ ) { int parInt = atoi(params[i]); float parFlt = atof(params[i]); // check if float if ( strchr ( params[i], '.' ) ) { msg.Add( parFlt ); } else if ( parInt != 0 ) { msg.Add( parInt ); } else { msg.Add( params[i] ); } } // we pack message into bundle when open if ( bundleOpen ) { theBundle.Add(new WOscMessage(msg)); } else { clientError = client.NetworkSend(msg.GetBuffer(), msg.GetBufferLen()); if ( clientError != WOscTcpClient::WOS_ERR_NO_ERROR ) { std::cout<<"Client transmit failed with: "<<WOscTcpClient::GetErrStr(clientError)<<std::endl; break; } } } catch(const WOscException& e ) { std::cout<<"Exception: " << e.GetErrStr() <<std::endl; } } // open bundle else if (input[0] == '[') { if ( bundleOpen ) { std::cout<<"Bundle already open."<<std::endl; } else { theBundle.Reset(); bundleOpen = true; } } // close bundle else if (input[0] == ']') { if ( bundleOpen ) { clientError = client.NetworkSend(theBundle.GetBuffer(), theBundle.GetBufferLen()); if ( clientError != WOscTcpClient::WOS_ERR_NO_ERROR ) { std::cout<<"Client transmit of bundle failed with: "<<WOscTcpClient::GetErrStr(clientError)<<std::endl; break; } bundleOpen = false; } else { std::cout<<"No bundle to close."<<std::endl; } } // other commands else { // exit command if ( strcmp("exit",input) == 0 ) { break; } // help command else if ( strcmp("help",input) == 0 ) { // std::cout << WOSC_CLIENT_HELP_STR ; } // set local port (slp) else if ( strncmp("slp",input,3) == 0 ) { /* localport = atoi( &input[4] ); std::cout << " Trying to set local port to " << localport << "."<<std::endl ; client.NetworkHalt(); if ( client.NetworkInit( localport ) != WOscClient::WOS_ERR_NO_ERROR ) { std::cout << "Exit."<<std::endl ; return -1; } std::cout << " Port successfully changed and network restarted."<<std::endl ; */ } // set remote port (srp) else if ( strncmp("srp",input,3) == 0 ) { /* remoteport = atoi( &input[4] ); std::cout << " Remote port set to " << remoteport << "."<<std::endl ; */ } // set remote IP (srip) else if ( strncmp("srip",input,4) == 0 ) { /* strcpy(remoteIP, &input[5]); std::cout << " Remote IP set to " << remoteIP << "."<<std::endl ; */ } } } clientError = client.Close(); if ( clientError != WOscTcpClient::WOS_ERR_NO_ERROR ) { std::cout<<"Client close failed with: "<<WOscTcpClient::GetErrStr(clientError)<<std::endl; return -1; } return 0; }