PageRenderTime 32ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/addons/ofxNetwork/src/ofxTCPServer.cpp

https://gitlab.com/minotnepal/LearnOpenFrameworks
C++ | 320 lines | 235 code | 55 blank | 30 comment | 49 complexity | 6419e7ee313267e6e837e59e03ae3821 MD5 | raw file
  1. #include "ofxTCPServer.h"
  2. #include "ofxTCPClient.h"
  3. #include "ofUtils.h"
  4. //--------------------------
  5. ofxTCPServer::ofxTCPServer(){
  6. connected = false;
  7. idCount = 0;
  8. port = 0;
  9. str = "";
  10. messageDelimiter = "[/TCP]";
  11. bClientBlocking = false;
  12. }
  13. //--------------------------
  14. ofxTCPServer::~ofxTCPServer(){
  15. close();
  16. }
  17. //--------------------------
  18. void ofxTCPServer::setVerbose(bool _verbose){
  19. ofLogWarning("ofxTCPServer") << "setVerbose(): is deprecated, replaced by ofLogWarning and ofLogError";
  20. }
  21. //--------------------------
  22. bool ofxTCPServer::setup(int _port, bool blocking){
  23. if( !TCPServer.Create() ){
  24. ofLogError("ofxTCPServer") << "setup(): couldn't create server";
  25. return false;
  26. }
  27. if( !TCPServer.Bind(_port) ){
  28. ofLogError("ofxTCPServer") << "setup(): couldn't bind to port " << _port;
  29. return false;
  30. }
  31. connected = true;
  32. port = _port;
  33. bClientBlocking = blocking;
  34. startThread(true, false);
  35. return true;
  36. }
  37. //--------------------------
  38. void ofxTCPServer::setMessageDelimiter(string delim){
  39. if(delim != ""){
  40. messageDelimiter = delim;
  41. }
  42. }
  43. //--------------------------
  44. bool ofxTCPServer::close(){
  45. if(!connected) return true;
  46. mConnectionsLock.lock();
  47. map<int,ofPtr<ofxTCPClient> >::iterator it;
  48. for(it=TCPConnections.begin(); it!=TCPConnections.end(); it++){
  49. it->second->close();
  50. }
  51. TCPConnections.clear();
  52. mConnectionsLock.unlock(); // unlock for thread
  53. stopThread();
  54. if( !TCPServer.Close() ){
  55. ofLogWarning("ofxTCPServer") << "close(): couldn't close connections";
  56. waitForThread(false); //stop the thread
  57. return false;
  58. }else{
  59. connected = false;
  60. waitForThread(false); //stop the thread
  61. return true;
  62. }
  63. }
  64. ofxTCPClient & ofxTCPServer::getClient(int clientID){
  65. return *TCPConnections.find(clientID)->second;
  66. }
  67. //--------------------------
  68. bool ofxTCPServer::disconnectClient(int clientID){
  69. ofMutex::ScopedLock Lock( mConnectionsLock );
  70. if( !isClientSetup(clientID) ){
  71. ofLogWarning("ofxTCPServer") << "disconnectClient(): client " << clientID << " doesn't exist";
  72. return false;
  73. }else if(getClient(clientID).close()){
  74. TCPConnections.erase(clientID);
  75. return true;
  76. }
  77. return false;
  78. }
  79. //--------------------------
  80. bool ofxTCPServer::send(int clientID, string message){
  81. ofMutex::ScopedLock Lock( mConnectionsLock );
  82. if( !isClientSetup(clientID) ){
  83. ofLogWarning("ofxTCPServer") << "send(): client " << clientID << " doesn't exist";
  84. return false;
  85. }else{
  86. getClient(clientID).send(message);
  87. if(!getClient(clientID).isConnected()) TCPConnections.erase(clientID);
  88. return true;
  89. }
  90. }
  91. //--------------------------
  92. bool ofxTCPServer::sendToAll(string message){
  93. ofMutex::ScopedLock Lock( mConnectionsLock );
  94. if(TCPConnections.size() == 0) return false;
  95. map<int,ofPtr<ofxTCPClient> >::iterator it;
  96. vector<int> disconnect;
  97. for(it=TCPConnections.begin(); it!=TCPConnections.end(); it++){
  98. if(it->second->isConnected()) it->second->send(message);
  99. else disconnect.push_back(it->first);
  100. }
  101. for(int i=0; i<(int)disconnect.size(); i++){
  102. TCPConnections.erase(disconnect[i]);
  103. }
  104. return true;
  105. }
  106. //--------------------------
  107. string ofxTCPServer::receive(int clientID){
  108. ofMutex::ScopedLock Lock( mConnectionsLock );
  109. if( !isClientSetup(clientID) ){
  110. ofLogWarning("ofxTCPServer") << "receive(): client " << clientID << " doesn't exist";
  111. return "client " + ofToString(clientID) + "doesn't exist";
  112. }
  113. if( !getClient(clientID).isConnected() ){
  114. disconnectClient(clientID);
  115. return "";
  116. }
  117. return getClient(clientID).receive();
  118. }
  119. //--------------------------
  120. bool ofxTCPServer::sendRawBytes(int clientID, const char * rawBytes, const int numBytes){
  121. ofMutex::ScopedLock Lock( mConnectionsLock );
  122. if( !isClientSetup(clientID) ){
  123. ofLogWarning("ofxTCPServer") << "sendRawBytes(): client " << clientID << " doesn't exist";
  124. return false;
  125. }
  126. else{
  127. return getClient(clientID).sendRawBytes(rawBytes, numBytes);
  128. }
  129. }
  130. //--------------------------
  131. bool ofxTCPServer::sendRawBytesToAll(const char * rawBytes, const int numBytes){
  132. ofMutex::ScopedLock Lock( mConnectionsLock );
  133. if(TCPConnections.size() == 0 || numBytes <= 0) return false;
  134. map<int,ofPtr<ofxTCPClient> >::iterator it;
  135. for(it=TCPConnections.begin(); it!=TCPConnections.end(); it++){
  136. if(it->second->isConnected())it->second->sendRawBytes(rawBytes, numBytes);
  137. }
  138. return true;
  139. }
  140. //--------------------------
  141. bool ofxTCPServer::sendRawMsg(int clientID, const char * rawBytes, const int numBytes){
  142. ofMutex::ScopedLock Lock( mConnectionsLock );
  143. if( !isClientSetup(clientID) ){
  144. ofLogWarning("ofxTCPServer") << "sendRawMsg(): client " << clientID << " doesn't exist";
  145. return false;
  146. }
  147. else{
  148. return getClient(clientID).sendRawMsg(rawBytes, numBytes);
  149. }
  150. }
  151. //--------------------------
  152. bool ofxTCPServer::sendRawMsgToAll(const char * rawBytes, const int numBytes){
  153. ofMutex::ScopedLock Lock( mConnectionsLock );
  154. if(TCPConnections.size() == 0 || numBytes <= 0) return false;
  155. map<int,ofPtr<ofxTCPClient> >::iterator it;
  156. for(it=TCPConnections.begin(); it!=TCPConnections.end(); it++){
  157. if(it->second->isConnected())it->second->sendRawMsg(rawBytes, numBytes);
  158. }
  159. return true;
  160. }
  161. //--------------------------
  162. int ofxTCPServer::getNumReceivedBytes(int clientID){
  163. ofMutex::ScopedLock Lock( mConnectionsLock );
  164. if( !isClientSetup(clientID) ){
  165. ofLogWarning("ofxTCPServer") << "getNumReceivedBytes(): client " << clientID << " doesn't exist";
  166. return 0;
  167. }
  168. return getClient(clientID).getNumReceivedBytes();
  169. }
  170. //--------------------------
  171. int ofxTCPServer::receiveRawBytes(int clientID, char * receiveBytes, int numBytes){
  172. ofMutex::ScopedLock Lock( mConnectionsLock );
  173. if( !isClientSetup(clientID) ){
  174. ofLogWarning("ofxTCPServer") << "receiveRawBytes(): client " << clientID << " doesn't exist";
  175. return 0;
  176. }
  177. return getClient(clientID).receiveRawBytes(receiveBytes, numBytes);
  178. }
  179. //--------------------------
  180. int ofxTCPServer::receiveRawMsg(int clientID, char * receiveBytes, int numBytes){
  181. ofMutex::ScopedLock Lock( mConnectionsLock );
  182. if( !isClientSetup(clientID) ){
  183. ofLogWarning("ofxTCPServer") << "receiveRawMsg(): client " << clientID << " doesn't exist";
  184. return 0;
  185. }
  186. return getClient(clientID).receiveRawMsg(receiveBytes, numBytes);
  187. }
  188. //--------------------------
  189. int ofxTCPServer::getClientPort(int clientID){
  190. ofMutex::ScopedLock Lock( mConnectionsLock );
  191. if( !isClientSetup(clientID) ){
  192. ofLogWarning("ofxTCPServer") << "getClientPort(): client " << clientID << " doesn't exist";
  193. return 0;
  194. }
  195. else return getClient(clientID).getPort();
  196. }
  197. //--------------------------
  198. string ofxTCPServer::getClientIP(int clientID){
  199. ofMutex::ScopedLock Lock( mConnectionsLock );
  200. if( !isClientSetup(clientID) ){
  201. ofLogWarning("ofxTCPServer") << "getClientIP(): client " << clientID << " doesn't exist";
  202. return "000.000.000.000";
  203. }
  204. else return getClient(clientID).getIP();
  205. }
  206. //--------------------------
  207. int ofxTCPServer::getNumClients(){
  208. ofMutex::ScopedLock Lock( mConnectionsLock );
  209. return TCPConnections.size();
  210. }
  211. //--------------------------
  212. int ofxTCPServer::getLastID(){
  213. return idCount;
  214. }
  215. //--------------------------
  216. int ofxTCPServer::getPort(){
  217. return port;
  218. }
  219. //--------------------------
  220. bool ofxTCPServer::isConnected(){
  221. return connected;
  222. }
  223. //--------------------------
  224. bool ofxTCPServer::isClientSetup(int clientID){
  225. return TCPConnections.find(clientID)!=TCPConnections.end();
  226. }
  227. //--------------------------
  228. bool ofxTCPServer::isClientConnected(int clientID){
  229. ofMutex::ScopedLock Lock( mConnectionsLock );
  230. return isClientSetup(clientID) && getClient(clientID).isConnected();
  231. }
  232. //don't call this
  233. //--------------------------
  234. void ofxTCPServer::threadedFunction(){
  235. ofLogVerbose("ofxTCPServer") << "listening thread started";
  236. while( isThreadRunning() ){
  237. int acceptId;
  238. for(acceptId = 0; acceptId <= idCount; acceptId++){
  239. if(!isClientConnected(acceptId)) break;
  240. }
  241. if(acceptId == TCP_MAX_CLIENTS){
  242. ofLogWarning("ofxTCPServer") << "no longer accepting connections, maximum number of clients reached: " << TCP_MAX_CLIENTS;
  243. break;
  244. }
  245. if( !TCPServer.Listen(TCP_MAX_CLIENTS) ){
  246. if(isThreadRunning()) ofLogError("ofxTCPServer") << "listening failed";
  247. }
  248. // we need to lock here, but can't as it blocks...
  249. // so use a temporary to not block the lock
  250. ofPtr<ofxTCPClient> client(new ofxTCPClient);
  251. if( !TCPServer.Accept( client->TCPClient ) ){
  252. if(isThreadRunning()) ofLogError("ofxTCPServer") << "couldn't accept client " << acceptId;
  253. }else{
  254. ofMutex::ScopedLock Lock( mConnectionsLock );
  255. // take owenership of socket from NewClient
  256. TCPConnections[acceptId] = client;
  257. TCPConnections[acceptId]->setup(acceptId, bClientBlocking);
  258. TCPConnections[acceptId]->setMessageDelimiter(messageDelimiter);
  259. ofLogVerbose("ofxTCPServer") << "client " << acceptId << " connected on port " << TCPConnections[acceptId]->getPort();
  260. if(acceptId == idCount) idCount++;
  261. }
  262. }
  263. idCount = 0;
  264. ofLogVerbose("ofxTCPServer") << "listening thread stopped";
  265. }