int main (int argc, char **argv) { OTLog::vOutput(0, "\n\nWelcome to Open Transactions... Test Server -- version %s\n" "(transport build: OTMessage -> TCP -> SSL)\n" "IF YOU PREFER TO USE XmlRpc with HTTP, then rebuild from main folder like this:\n\n" "cd ..; make clean; make rpc\n\n", OTLog::Version()); // ----------------------------------------------------------------------- // This object handles all the actual transaction notarization details. // (This file you are reading is a wrapper for OTServer, which adds the transport layer.) OTServer theServer; // ----------------------------------------------------------------------- #ifdef _WIN32 WSADATA wsaData; WORD wVersionRequested = MAKEWORD( 2, 2 ); int err = WSAStartup( wVersionRequested, &wsaData ); /* Tell the user that we could not find a usable */ /* Winsock DLL. */ OT_ASSERT_MSG((err == 0), "WSAStartup failed!\n"); /* Confirm that the WinSock DLL supports 2.2. */ /* Note that if the DLL supports versions greater */ /* than 2.2 in addition to 2.2, it will still return */ /* 2.2 in wVersion since that is the version we */ /* requested. */ bool bWinsock = (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2); /* Tell the user that we could not find a usable */ /* WinSock DLL. */ if (!bWinsock) WSACleanup(); // do cleanup. OT_ASSERT_MSG((!bWinsock), "Could not find a usable version of Winsock.dll\n"); /* The Winsock DLL is acceptable. Proceed to use it. */ /* Add network programming using Winsock here */ /* then call WSACleanup when done using the Winsock dll */ OTLog::vOutput(0,"The Winsock 2.2 dll was found okay\n"); #endif OTLog::vOutput(0, "\n\nWelcome to Open Transactions, version %s.\n\n", OTLog::Version()); // ----------------------------------------------------------------------- // The beginnings of an INI file!! #ifndef _WIN32 // if UNIX (NOT windows) wordexp_t exp_result; wordexp(OT_INI_FILE_DEFAULT, &exp_result, 0); const OTString strIniFileDefault(exp_result.we_wordv[0]); wordfree(&exp_result); #else const OTString strIniFileDefault(OT_INI_FILE_DEFAULT); #endif OTString strPath(SERVER_PATH_DEFAULT); { CSimpleIniA ini; SI_Error rc = ini.LoadFile(strIniFileDefault.Get()); if (rc >=0) { const char * pVal = ini.GetValue("paths", "server_path", SERVER_PATH_DEFAULT); // todo stop hardcoding. if (NULL != pVal) { strPath.Set(pVal); OTLog::vOutput(0, "Reading ini file (%s). \n Found Server data_folder path: %s \n", strIniFileDefault.Get(), strPath.Get()); } else { strPath.Set(SERVER_PATH_DEFAULT); OTLog::vOutput(0, "Reading ini file (%s): \n Failed reading Server data_folder path. Using: %s \n", strIniFileDefault.Get(), strPath.Get()); } } else { strPath.Set(SERVER_PATH_DEFAULT); OTLog::vOutput(0, "Unable to load ini file (%s) to find data_folder path\n Will assume that server data_folder is at path: %s \n", strIniFileDefault.Get(), strPath.Get()); } } // ----------------------------------------------------------------------- OTString strCAFile, strDHFile, strKeyFile; //, strSSLPassword; if (argc < 1) { OTLog::vOutput(0, "\n==> USAGE: %s [absolute_path_to_data_folder]\n\n" // OTLog::vOutput(0, "\n==> USAGE: %s <SSL-password> [absolute_path_to_data_folder]\n\n" #if defined (FELLOW_TRAVELER) // "(Password defaults to '%s' if left blank.)\n" "(Folder defaults to '%s' if left blank.)\n" #else "The test password is always 'test'.\n" "OT will try to read the data_folder path from your ini file. If you prefer\n" "to specify it at the command line, and you want to see the exact path, type:\n" " cd data_folder && pwd && cd ..\n" #endif "\n\n", argv[0] #if defined (FELLOW_TRAVELER) // , KEY_PASSWORD, , strPath.Get() #endif ); #if defined (FELLOW_TRAVELER) // strSSLPassword.Set(KEY_PASSWORD); OTLog::SetMainPath(strPath.Get()); #else exit(1); #endif } else if (argc < 2) { // strSSLPassword.Set(argv[1]); OTLog::SetMainPath(strPath.Get()); } else { // strSSLPassword.Set(argv[1]); OTLog::SetMainPath(argv[1]); // formerly [2] } OTLog::vOutput(0, "Using as path to data folder: %s\n", OTLog::Path()); strCAFile. Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), CA_FILE); strDHFile. Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), DH_FILE); strKeyFile.Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), KEY_FILE); // ----------------------------------------------------------------------- // Init loads up server's nym so it can decrypt messages sent in envelopes. // It also does various other initialization work. // // (Envelopes prove that ONLY someone who actually had the server contract, // and had loaded it into his wallet, could ever connect to the server or // communicate with it. And if that person is following the contract, there // is only one server he can connect to, and one key he can use to talk to it.) OTLog::Output(0, "\n\nNow loading the server nym, which will also ask you for a password, to unlock\n" "its private key. (Default password is \"test\".)\n"); // Initialize SSL -- This MUST occur before any Private Keys are loaded! SFSocketGlobalInit(); // Any app that uses OT has to initialize SSL first. theServer.Init(); // Keys, etc are loaded here. // ----------------------------------------------------------------------- // We're going to listen on the same port that is listed in our server contract. // // OTString strHostname; // The hostname of this server, according to its own contract. int nPort=0; // The port of this server, according to its own contract. OT_ASSERT_MSG(theServer.GetConnectInfo(strHostname, nPort), "Unable to find my own connect info (which is in my server contract BTW.)\n"); const int nServerPort = nPort; // ----------------------------------------------------------------------- SFSocket *socket = NULL; listOfConnections theConnections; // Alloc Socket socket = SFSocketAlloc(); OT_ASSERT_MSG(NULL != socket, "SFSocketAlloc Failed\n"); // Initialize SSL Socket int nSFSocketInit = SFSocketInit(socket, strCAFile.Get(), strDHFile.Get(), strKeyFile.Get(), strSSLPassword.Get(), NULL); OT_ASSERT_MSG(nSFSocketInit >= 0, "SFSocketInit Context Failed\n"); // Listen on Address/Port int nSFSocketListen = SFSocketListen(socket, INADDR_ANY, nServerPort); OT_ASSERT_MSG(nSFSocketListen >= 0, "nSFSocketListen Failed\n"); theServer.ActivateCron(); do { SFSocket * clientSocket = NULL; // Accept Client Connection if (NULL != (clientSocket = SFSocketAccept(socket))) { OTClientConnection * pClient = new OTClientConnection(*clientSocket, theServer); theConnections.push_back(pClient); OTLog::Output(0, "Accepting new connection.\n"); } // READ THROUGH ALL CLIENTS HERE, LOOP A LIST // AND process in-buffer onto our list of messages. OTClientConnection * pConnection = NULL; for (listOfConnections::iterator ii = theConnections.begin(); ii != theConnections.end(); ++ii) { if (pConnection = *ii) { // Here we read the bytes from the pipe into the client's buffer // As necessary this function also processes those bytes into OTMessages // and adds them to the Input List for that client. pConnection->ProcessBuffer(); } } // Now loop through them all again, and process their messages onto the reply list. pConnection = NULL; for (listOfConnections::iterator ii = theConnections.begin(); ii != theConnections.end(); ++ii) { if (pConnection = *ii) { OTMessage * pMsg = NULL; while (pMsg = pConnection->GetNextInputMessage()) { OTMessage * pReply = new OTMessage; OT_ASSERT(NULL != pReply); if (theServer.ProcessUserCommand(*pMsg, *pReply, pConnection)) { OTLog::vOutput(0, "Successfully processed user command: %s.\n", pMsg->m_strCommand.Get()); pConnection->AddToOutputList(*pReply); } else { OTLog::Output(0, "Unable to process user command in XML, or missing payload, in main.\n"); delete pReply; pReply = NULL; } // I am responsible to delete this here. delete pMsg; pMsg = NULL; } } } // Now loop through them all again, and process their replies down the pipe pConnection = NULL; for (listOfConnections::iterator ii = theConnections.begin(); ii != theConnections.end(); ++ii) { if (pConnection = *ii) { OTMessage * pMsg = NULL; while (pMsg = pConnection->GetNextOutputMessage()) { pConnection->ProcessReply(*pMsg); // I am responsible to delete this here. delete pMsg; pMsg = NULL; } } } // The Server now processes certain things on a regular basis. // This method call is what gives it the opportunity to do that. theServer.ProcessCron(); // Now go to sleep for a tenth of a second. // (Main loop processes ten times per second, currently.) OTLog::SleepMilliseconds(100); // 100 ms == (1 second / 10) } while (1); // Close and Release Socket Resources SFSocketRelease(socket); #ifdef _WIN32 WSACleanup(); #endif return(0); }
int main (int argc, char **argv) { OTLog::vOutput(0, "\n\nWelcome to Open Transactions... Test Server -- version %s\n" "(transport build: OTMessage -> TCP -> SSL)\n" "NOTE: IF YOU PREFER TO USE XmlRpc with Http transport, then rebuild using:\n" "\"make -f Makefile.rpc\" (but make sure the client is built the same way.)\n\n", OTLog::Version()); // ----------------------------------------------------------------------- // This object handles all the actual transaction notarization details. // (This file you are reading is a wrapper for OTServer, which adds the transport layer.) OTServer theServer; // ----------------------------------------------------------------------- #ifdef _WIN32 WSADATA wsaData; WORD wVersionRequested = MAKEWORD( 2, 2 ); int nWSA = WSAStartup( wVersionRequested, &wsaData ); OT_ASSERT_MSG(0 != nWSA, "Error calling WSAStartup.\n"); #endif OTLog::vOutput(0, "\n\nWelcome to Open Transactions, version %s.\n\n", OTLog::Version()); // ----------------------------------------------------------------------- OTString strCAFile, strDHFile, strKeyFile, strSSLPassword; if (argc < 2) { OTLog::vOutput(0, "Usage: transaction <SSL-password> <data_folder path>\n\n" "(Password defaults to '%s' if left blank on the command line.)\n" "(Folder defaults to '%s' if left blank.)\n", KEY_PASSWORD, SERVER_PATH_DEFAULT); strSSLPassword.Set(KEY_PASSWORD); OTLog::SetMainPath(SERVER_PATH_DEFAULT); } else if (argc < 3) { OTLog::vOutput(0, "Usage: transaction <SSL-password> <data_folder path>\n\n" "(Folder defaults to '%s' if left blank.)\n", SERVER_PATH_DEFAULT); strSSLPassword.Set(argv[1]); OTLog::SetMainPath(SERVER_PATH_DEFAULT); } else { strSSLPassword.Set(argv[1]); OTLog::SetMainPath(argv[2]); } strCAFile. Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), CA_FILE); strDHFile. Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), DH_FILE); strKeyFile.Format("%s%s%s", OTLog::Path(), OTLog::PathSeparator(), KEY_FILE); // ----------------------------------------------------------------------- // Init loads up server's nym so it can decrypt messages sent in envelopes. // It also does various other initialization work. // // (Envelopes prove that ONLY someone who actually had the server contract, // and had loaded it into his wallet, could ever connect to the server or // communicate with it. And if that person is following the contract, there // is only one server he can connect to, and one key he can use to talk to it.) OTLog::Output(0, "\n\nNow loading the server nym, which will also ask you for a password, to unlock\n" "its private key. (Default password is \"test\".)\n"); // Initialize SSL -- This MUST occur before any Private Keys are loaded! SFSocketGlobalInit(); // Any app that uses OT has to initialize SSL first. theServer.Init(); // Keys, etc are loaded here. // ----------------------------------------------------------------------- // We're going to listen on the same port that is listed in our server contract. // // OTString strHostname; // The hostname of this server, according to its own contract. int nPort=0; // The port of this server, according to its own contract. OT_ASSERT_MSG(theServer.GetConnectInfo(strHostname, nPort), "Unable to find my own connect info (which is in my server contract BTW.)\n"); const int nServerPort = nPort; // ----------------------------------------------------------------------- SFSocket *socket = NULL; listOfConnections theConnections; // Alloc Socket socket = SFSocketAlloc(); OT_ASSERT_MSG(NULL != socket, "SFSocketAlloc Failed\n"); // Initialize SSL Socket int nSFSocketInit = SFSocketInit(socket, strCAFile.Get(), strDHFile.Get(), strKeyFile.Get(), strSSLPassword.Get(), NULL); OT_ASSERT_MSG(nSFSocketInit >= 0, "SFSocketInit Context Failed\n"); // Listen on Address/Port int nSFSocketListen = SFSocketListen(socket, INADDR_ANY, nServerPort); OT_ASSERT_MSG(nSFSocketListen >= 0, "nSFSocketListen Failed\n"); theServer.ActivateCron(); do { SFSocket * clientSocket = NULL; // Accept Client Connection if (NULL != (clientSocket = SFSocketAccept(socket))) { OTClientConnection * pClient = new OTClientConnection(*clientSocket, theServer); theConnections.push_back(pClient); OTLog::Output(0, "Accepting new connection.\n"); } // READ THROUGH ALL CLIENTS HERE, LOOP A LIST // AND process in-buffer onto our list of messages. OTClientConnection * pConnection = NULL; for (listOfConnections::iterator ii = theConnections.begin(); ii != theConnections.end(); ++ii) { if (pConnection = *ii) { // Here we read the bytes from the pipe into the client's buffer // As necessary this function also processes those bytes into OTMessages // and adds them to the Input List for that client. pConnection->ProcessBuffer(); } } // Now loop through them all again, and process their messages onto the reply list. pConnection = NULL; for (listOfConnections::iterator ii = theConnections.begin(); ii != theConnections.end(); ++ii) { if (pConnection = *ii) { OTMessage * pMsg = NULL; while (pMsg = pConnection->GetNextInputMessage()) { OTMessage * pReply = new OTMessage; OT_ASSERT(NULL != pReply); if (theServer.ProcessUserCommand(*pMsg, *pReply, pConnection)) { OTLog::vOutput(0, "Successfully processed user command: %s.\n", pMsg->m_strCommand.Get()); pConnection->AddToOutputList(*pReply); } else { OTLog::Output(0, "Unable to process user command in XML, or missing payload, in main.\n"); delete pReply; pReply = NULL; } // I am responsible to delete this here. delete pMsg; pMsg = NULL; } } } // Now loop through them all again, and process their replies down the pipe pConnection = NULL; for (listOfConnections::iterator ii = theConnections.begin(); ii != theConnections.end(); ++ii) { if (pConnection = *ii) { OTMessage * pMsg = NULL; while (pMsg = pConnection->GetNextOutputMessage()) { pConnection->ProcessReply(*pMsg); // I am responsible to delete this here. delete pMsg; pMsg = NULL; } } } // The Server now processes certain things on a regular basis. // This method call is what gives it the opportunity to do that. theServer.ProcessCron(); // Now go to sleep for a tenth of a second. // (Main loop processes ten times per second, currently.) OTLog::SleepMilliseconds(100); // 100 ms == (1 second / 10) } while (1); // Close and Release Socket Resources SFSocketRelease(socket); #ifdef _WIN32 WSACleanup(); #endif return(0); }